Why can't you use 'this' in member initializers?

C#

C# Problem Overview


> 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 curious as to why one is allowed and the other isn't.

Thanks, Alex

C# Solutions


Solution 1 - C#

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.

Solution 2 - C#

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.

Solution 3 - C#

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"

Solution 4 - C#

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.

Solution 5 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexCView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Darin DimitrovView Answer on Stackoverflow
Solution 3 - C#F.B. ten KateView Answer on Stackoverflow
Solution 4 - C#Matías FidemraizerView Answer on Stackoverflow
Solution 5 - C#Truong Hong ThiView Answer on Stackoverflow