0

Take a look at this code.

public struct Customer
{
    private int _id;
    private string _name;

    public int Id
    {
        get { return this._id; }
        set { this._id = value; }
    }

    public Customer(int Id, string Name)
    {
        this.Id = Id; // Error - CS0188: The 'this' object cannot be used before all of its fields are assigned to.
        this._name = Name;
    }
}

` Why do I get this error on the above line.

Now look at this code.

public struct Customer
{
    private string _name;
    public int Id { get; set; }

    public Customer(int Id, string Name)
    {
        this.Id = Id; // No error recieved.
        this._name = Name;
    }
}

In the above code I implemented Id as an Auto-Implemented property. This time I don't get any errors. Why?

Just to make it clear following link does not have my answer.

Compilation error. Using properties with struct

gamerdev
  • 65
  • 6
  • Make it set the field, not the property. – Wai Ha Lee Dec 03 '17 at 14:34
  • 3
    Possible duplicate of [Compilation error. Using properties with struct](https://stackoverflow.com/questions/4335773/compilation-error-using-properties-with-struct) – Wai Ha Lee Dec 03 '17 at 14:35
  • 4
    Just as an FYI, those are terrible naming. It should read `public Customer(int id, string name) { Id = id; Name = name; }` – Camilo Terevinto Dec 03 '17 at 14:36
  • I know that's terrible naming, I did that so you wouldn't give me the answer you gave @Camilo Terevinto. I could have did it your way but I just want to know why can't I use "this" keyword. – gamerdev Dec 05 '17 at 11:08

2 Answers2

1

You need to initialize all the fields of struct first. When you assign a value to an Auto-Implemented property it always sets the backing field, however, with custom setters, it's not always guaranteed. That's why you don't get any error

For custom properties:

public struct Customer
{
    private int _id;
    private string _name;

    public int Id
    {
        get { return this._id; }
        set { this._id = value; }
    }

    public Customer(int Id, string Name)
    {
        _id=0;
        this._name = Name;
        this.Id = Id; // This will work now
    }
}
Aman B
  • 2,276
  • 1
  • 18
  • 26
  • Last paragraph of @Damien_The_Unbeliever 's answer is key here. – Aman B Dec 05 '17 at 11:44
  • In an auto-implemented property it will always update the backing field, however, a normal property might do something other than updating the backing field – Aman B Dec 05 '17 at 11:45
  • Thanks you helped me. – gamerdev Dec 05 '17 at 11:47
  • The second sentence is wrong. If the second code sample did *nothing* with `Id` and then tried to use `this` in a context requiring definite assignment, it would still generate the error. The fact that the second code sample doesn't do anything that requires definite assignment is why it fails to generate an error, not a default assignment to the property. – Damien_The_Unbeliever Dec 05 '17 at 12:08
  • Yep, thats what Learner pointed out above. Edited the answer to reflect that. Thanks – Aman B Dec 05 '17 at 13:36
  • Thanks. To initialize all fields to the default value, the struct constructor can inherit from this(). `public SomeStructConstructor(somParameters) : this() { /*logic here*/ }` – Forestrf Aug 24 '19 at 16:30
1

Under C# 5, both methods should generate an error. From Automatically Implemented Properties:

This restriction also means that definite assignment of struct types with auto-implemented properties can only be achieved using the standard constructor of the struct, since assigning to the property itself requires the struct to be definitely assigned. This means that user-defined constructors must call the default constructor.

However, C# 6 introduced read-only auto-implemented properties and introduced this language (whilst removing the above language):

a getter-only auto-property can also be assigned to in the body of a constructor of the enclosing class. Such an assignment assigns directly to the readonly backing field of the property.

I suspect that they changed all assignments for Automatically Implemented Properties (not just for readonly) in constructors to assign to the backing field rather than use the accessor. This is known to be "safe" since the accessor doesn't contain any custom code - unlike the situation in your first example where the set accessor could do anything, including leaking the not-definitely-assigned this outside of the current struct.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448