Автоматически реализованное свойство в структуре не может быть назначено

У меня есть следующий код:

struct T 
{
    public T(int u) 
    { 
        this.U = 10; //Errors are here
    }

    public int U { get; private set;  }
}

Компилятор С# дает мне пару ошибок в указанной строке: 1) Поле резервного копирования для автоматически реализуемого свойства "TestConsoleApp.Program.T.U" должно быть полностью назначено до того, как элемент управления будет возвращен вызывающему. Рассмотрим вызов конструктора по умолчанию из инициализатора конструктора. 2) Объект 'this' не может использоваться до того, как все его поля будут присвоены

Чем я ошибаюсь? Помогите мне понять.

Ответ 1

Из спецификации С#:

10.7.3 Автоматически реализованные свойства

Когда свойство указано как автоматически реализуемое свойство, скрытое резервное поле автоматически доступно для этого объекта, и аксессоры реализуются для чтения и записи на поле поддержки.

[Исключен]

Поскольку поле поддержки недоступно, оно может быть прочитано и записано только через аксессоры свойств, даже внутри содержащего типа.

[Исключен]

Это ограничение также означает, что определенное назначение типов структуры с автоматически реализованными свойствами могут быть достигнуты только с помощью стандартный конструктор структуры, так как присваивание свойства сам требует, чтобы структура была определенно назначена. Это значит, что определяемые пользователем конструкторы должны вызывать конструктор по умолчанию.

Итак, вам это нужно:

struct T 
{
    public T(int u)
        : this()
    { 
        this.U = u;
    }

    public int U { get; private set; }
}

Ответ 2

Ну, для начала вы создаете изменчивую структуру - это почти всегда очень плохая идея. Взаимозаменяемые структуры иногда могут вести себя так, как вы этого не ожидаете. Хорошо, это только конфиденциально изменчиво, но тот факт, что вы написали код, чтобы мутировать его, - это плохой знак.

Причиной второй ошибки является то, что вы не можете использовать какие-либо свойства или методы структуры до тех пор, пока не будут назначены все поля, поэтому вам необходимо привязать к неявному беззаметному конструктору:

public T(int u) : this()
{ 
    this.U = 10;
}

Компилятор требует, чтобы любой конструктор оставил все поля определенно назначенными (именно поэтому вы до этого добыли первую ошибку, компилятор не "знает", что свойство присваивает поле значение) - путем привязки к this(), вы убедитесь, что к тому моменту, когда вы дойдете до своего тела конструктора, все поля уже определенно назначены, и вам больше не нужно об этом беспокоиться.

Однако, если вы действительно не хотите разрешить мутацию, я предлагаю вам просто сделать это подлинно доступным только для чтения:

struct T 
{
    private readonly int u;

    public T(int u)
    { 
        this.u = 10;
    }

    public int U { get { return u; } }
}

Теперь более очевидно, что вы не хотите мутировать его даже внутри самой структуры.

Ответ 3

Добавить вызов конструктора по умолчанию:

public T(int u) : this() 
{
    this.U = 10;
}

Ответ 4

вам нужно использовать конструктор по умолчанию:

struct T
{
    public int U { get; private set; }

    public T(int u) : this()
    {
        U = 10;
    }


}