Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is `this` not available in C# 6.0 Auto-Property Initialization?

I have the following code class:

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

    public class Nested
    {
        public Nested(Foo foo)
        {
            foo.DoSomething();
        }
    }

    private void DoSomething()
    {

    }
}

However, I get this compile error:

Keyword 'this' is not available in the current context

I can fix it by simply not using Auto-Property Initializer, and explicitly move it into a constructor instead:

public Nested Bar { get; }

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

Why is it so? Isn't Auto-Property Initializer actually translated into constructor code in IL?

like image 323
Luke Vo Avatar asked May 15 '17 10:05

Luke Vo


People also ask

Can you use this in C?

In C you do not have the this keyword. Only in C++ and in a class, so your code is C and you use your this variable as a local method parameter, where you access the array struct.

Why gets () is not working in C?

Show activity on this post. It's because gets() it's so incredibly dangerous to use, that some C libraries have removed it completely and replaced it with a version that does nothing. Use fgets() instead.

What is Gets_s in C?

The gets_s function reads a line from the standard input stream stdin and stores it in buffer . The line consists of all characters up to and including the first newline character (' \n '). gets_s then replaces the newline character with a null character (' \0 ') before returning the line.

What does C++ have that C does not?

C++ was developed by Bjarne Stroustrup in 1979. C does no support polymorphism, encapsulation, and inheritance which means that C does not support object oriented programming. C++ supports polymorphism, encapsulation, and inheritance because it is an object oriented programming language.


2 Answers

Simply: you can't use this in initializers. The idea is to prevent an incomplete object from escaping - Nested(this) could do anything to your object, leading to very confusing and hard to understand bugs. Keep in mind that initializers execute before any constructor that you add. The same thing fails for field initializers too, in exactly the same way:

private Nested _field = new Nested(this);

Essentially, initializers are intended to perform simple initializations - fixing the 98% problem. Anything involving this is more complex, and you'll need to write your own constructor - and take the blame for any timing issues :)

like image 78
Marc Gravell Avatar answered Oct 22 '22 17:10

Marc Gravell


Why is it so? Isn't Auto-Property Initializer actually translated into constructor code in IL?

The rules for automatically implemented property initializers are the same as those for field initializers, for the same reason. Note that property initializers are executed before base class bodies, just like field initializers - so you're still in the context of a "somewhat uninitialized" object; more so than during a constructor body.

So you should imagine that the property is being converted into this:

private readonly Nested bar = new Nested(this); // Invalid

public Nested Bar
{
    get { return bar; }
}

In short, this restriction is to stop you from getting yourself into trouble. If you need to refer to this when initializing a property, just do it manually in a constructor, as per your second example. (It's relatively rare in my experience.)

like image 24
Jon Skeet Avatar answered Oct 22 '22 17:10

Jon Skeet