Why does the first constructor in ClassA cause the compiler error 'cannot use "this" in member intializer'?
... or how can i get this to work?
Thanks
public sealed class ClassA : IMethodA
{
private readonly IMethodA _methodA;
public ClassA():this(this)
{}
public ClassA(IMethodA methodA)
{
_methodA = methodA;
}
public void Run(int i)
{
_methodA.MethodA(i);
}
public void MethodA(int i)
{
Console.WriteLine(i.ToString());
}
}
public interface IMethodA
{
void MethodA(int i);
}
-
You are allowed to use the
this(...)
syntax to invoke another constructor at the same level - however, you cannot usethis
(the current instance) in this context.The easiest option here is to duplicate the assignment code (
_methodA = methodA
).Another option might be null-coalescing:
public ClassA():this(null) {} public ClassA(IMethodA methodA) { // defaults to "this" if null _methodA = methodA ?? this; }
Bobby Cannon : @Marc Gravell: beat me to it... -
This is called out in section 10.11.1 of the C# spec
An instance constructor initializer cannot access the instance being created. Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple-name.
There is no way to get this to work with an instance constructor because this cannot be accessed. What you could do is make the constructor private, create an initialization method and a static constructor.
public sealed class ClassA : IMethodA { private ClassA() { } private void Initialize(IMethodA param) { ... } public static ClassA Create() { var v1 = new ClassA(); v1.Initialize(v1); return v1; } public static ClassA Create(IMethodA param) { var v1 = new ClassA(); v1.Initialize(param); return v1; } }
-
You're trying to pass the object before it is constructed. Although the compiler could do something sensible in this case, in general that won't work.
Your actual example works if you just do this:
public ClassA() { _methodA = this; }
But you probably want to share more logic, so just use a function.
public ClassA() { SetStuff(); _methodA = this; } public ClassA(IMethodA methodA) { SetStuff(); _methodA = methodA; }
Marc Gravell : Note that you can still use SetStuff with readonly fields... *if* you use a `ref` / `out` argument. Whether it is worth it depends on the scenario. -
You can't use the
this
keyword when chaining constructors essentially becausethis
refers to an object that hasn't been instantiated yet (creation of the object doesn't begin until some (the top-level or base) constructor block has been entered). Moreover, why exactly would you want to do this? It seems rather pointless when you have access to thethis
keyword everywhere.I recommend simply using independent constructors as such:
public sealed class ClassA : IMethodA { private readonly IMethodA _methodA; public ClassA() { _methodA = this; } public ClassA(IMethodA methodA) { _methodA = methodA; } }
Perhaps I misunderstand what you're trying to do, but hopefully that will solve the issue for you.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.