tags:

views:

161

answers:

5

Why does this produce a compiler error:

class Foo
{
    public Bar Baz = new Bar(this);
}

But this does not:

class Foo
{
    public Bar Baz;

    public Foo()
    {
        this.Baz = new Bar(this);
    }
}

Conceptually the two are equivalent, are they not?

+1  A: 

It is not logical to access the class that is not initialized yet. If you would be able to access this it would mean that Bar is already initialized that is not true till the constructor is not finished.

Jenea
And it is supposed to be "initialized" in the middle of the constructor?
Vilx-
No, but at least in the middle of the constructor you can rely upon two things. (1) all the field initializers on both derived and base classes are fully executed and (2) all base class constructors are fully executed. That gives you a lot more confidence when using "this" in a constructor body. Were we to allow you to use "this" in a field initializer, neither of those two things would be true, which would increase the risk of error.
Eric Lippert
+1  A: 

Because at that point (in you first example) the object has not been constructed yet. In the constructor it is already.

In the constructor body you have an option to do extra initialization but only if you wish - change field values, call other methods, whatever. But this is optional. So you may count on a technically constructed object here, while it may not be really constructed according to your application logic. But then it is you who has to watch out, not compiler any more.

Developer Art
What do you mean by "has not been constructed yet"?
Vilx-
+1  A: 

Because the class you're referencing hasn't been initialised yet.

Kieron
+8  A: 

No, they're not quite equivalent... the variable initializer executes before any base class constructors are run. The body of the constructor executes after base class constructors are run. (This is different from Java, where variable initializers execute after base class constructors but before the constructor body.)

Therefore it's safer to access this within the constructor body: you can be sure that the object is initialized at least in respect to its base class (and upwards).

I believe that's the reasoning, anyway...

Jon Skeet
nice one mr jon skeet :)
baeltazor
If you could call an instance method from a field initializer, you could call a member method of the base type, and the body of that method would run before the object was initialized, defeating a very basic language contract (that the constructor runs when the object is created).
280Z28
Well, you can sort of do that anyway - you can call a virtual member implemented in a derived class before that derived class's constructor body has run. That's generally frowned upon though.
Jon Skeet
Ahh, so the basic idea is to make it so, that a method of a class will never be called before the constructor has at least started to execute. Makes sense.
Vilx-
Yes, that is the reasoning. Some notes on related matters: http://blogs.msdn.com/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx and http://blogs.msdn.com/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx
Eric Lippert
+1  A: 
class Foo
{
    public Bar Baz = new Bar(this);
}

"this" represents the object of a "Foo" class. And you don't have the class object initiated at this point.

Suppose, "Bar" constructor don't need the "Foo" instance to initiate (or call its constructor) like Bar("hello!") then the above statement could be compiled as:

class Foo
{
    public static Bar Baz = new Bar("Hello!");
}

Which can be accessed through:

Foo.Baz.something();

A class can initiate an instance which should be marked with "static" keyword and don't need the class instance to initiate.

Ramiz Uddin
Say what? O_o
Vilx-