开发者

Why can't you use 'this' in member initializers? [duplicate]

This question already has answers here: Closed 10 years ago.

Possible Duplicate:

Cannot use ‘this’ in member initializer?

Any ideas why I get an error if I try to do something like this:

public class Bar
{
    public Bar(Foo foo)
    {
    }
}

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

I get an error saying:

"Cannot use 'this' in member initializer"

but the following works:

public class Foo
{
    private Bar _bar;

    public Foo()
    {
        _bar = new Bar(this);
    }
}

Anyone know the reason behind this? My understanding was that these would compile to the same IL, so am curiou开发者_如何学Gos as to why one is allowed and the other isn't.

Thanks, Alex


I suspect it's to prevent you from using the object before at least the base class constructor has run, ensuring that all the base class members are appropriately initialized. (Variable initializers are executed before the base class constructor, whereas the constructor body is executed after that.)

Will check whether the annotated spec has anything to say about this when I'm next near it...

EDIT: The C# 4 annotated spec doesn't have any explanation. Just (in 10.5.5.2):

A variable initializer for an instance field cannot reference the instance being created.


Field initializers run before base class constructors so this doesn't yet exist. It exists only once the base constructor has finished executing.

17.10.2 Instance variable initializers:

When an instance constructor has no constructor initializer, or it has a constructor initializer of the form base(...), that constructor implicitly performs the initializations specified by the variable-initializers of the instance fields declared in its class. This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor and before the implicit invocation of the direct base class constructor. The variable initializers are executed in the textual order in which they appear in the class declaration.


I believe this is because fields initialize before the class initializes so when the following code is run:

private Bar _bar = new Bar(this);

"this" has no actual value to be referenced.

While putting it in the constructor means that there is an instance of "Foo" referencable by "this"


Member initializers run before class constructor. Consider that you might have many member initializers in a single class.

If you use 'this' in constructor -> all members with initializers were initialized. So everything is OK.

If you use 'this' in member initializer: other members (with initializers attached) might not be initialized yet -> 'this' is not yet ready. That is why using 'this' is not allowed here is not allowed.


In C#, no logic is intended to be outside methods' and properties' bodies.

Field initializers are an exception, but with some limitations.

It'd wrong getting a reference of current object with this keyword because a class field declaration isn't logic but class design, while this is part of run-time semantics.

By the way, it seems it's a C# design decision, because, in fact, a field initializer runs during class construction, so "current instance of declaring class" should be available through this. But again, what would be this outside a method or property body scope?

As Jon Skeet and others pointed, this isn't available because field initializers are executed after base constructor execution.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜