Pergunta

Ultra simple question... How does one properly initialize private backing fields on a structure? I get a compiler error:

Backing field for automatically implemented property 'Rectangle.Y' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.

Heres the source code.

public struct Rectangle
{    
    public Rectangle(int x, int y, int width, int height)
    {
        X = x; 
        Y = y; 
        Width = width; 
        Height = height;
    }
    public int Width { get; private set; }
    public int Height { get; private set; }
    public int X { get; private set; }
    public int Y { get; private set; }
}
Foi útil?

Solução

This is a problem using automatically implemented properties in structs. You need to explicitly chain to the parameterless constructor:

public Rectangle(int x, int y, int width, int height) : this()
{
    X = x; 
    Y = y; 
    Width = width; 
    Height = height;
}

The compiler doesn't "know" that setting each of the properties will set the relevant fields - it needs to see that all the fields (which you can't access explicitly because they're being autogenerated) are assigned. Fortunately the parameterless constructor does that for you.

Personally I'd just use real readonly fields and manual properties instead, mind you:

public struct Rectangle
{    
    private readonly int x, y, width, height;

    public int X { get { return x; } }
    public int Y { get { return y; } }
    public int Width { get { return width; } }
    public int Height{ get { return height; } }

    public Rectangle(int x, int y, int width, int height)
    {
        this.x = x; 
        this.y = y; 
        this.width = width; 
        this.height = height;
    }
}

I wish C# had a way of declaring "really" readonly automatically implemented properties, such that the setters could only be called in the constructor and would be translated directly to writes to readonly fields, but never mind...

Outras dicas

If you chain-call the default constructor (which will default-initialize the backing fields for you, satisfying the compiler) you can avoid that error.

public Rectangle(int x, int y, int width, int height)
    : this()
{
    // ...

Unless you have a particular reason for using autoproperties rather than fields, simply use public fields. Class properties can do useful things fields cannot (e.g. supporting update notification), and using auto-properties in a class type to start with (rather than fields) will make it easier to use real properties later if such extra features become necessary. Mutable structure properties don't really offer any of the advantages associated with class properties. Given the declarations:

SomeStructure foo,bar;
...
foo = bar;

the last statement will capture the state of all of bar's public and private fields, and overwrite with those the contents of all of foo's public and private fields, without any code associated with SomeStructure having any power to stop it or even know that it has happened. If the semantics of a struct are that members can hold any combination of values which are valid for their respective types, using properties rather than fields will make some operations less convenient (such as the initialization at issue) while offering essentially no protection or other advantages to speak of.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top