Автоматически реализованное свойство в структуре не может быть назначено - PullRequest
24 голосов
/ 06 октября 2011

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

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

    public int U { get; private set;  }
}

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

Что я делаю неправильно?Помоги мне понять.

Ответы [ 5 ]

73 голосов
/ 06 октября 2011

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

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

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

[Удалено]

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

[Удалено]

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

Так что вам нужно это:

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

    public int U { get; private set; }
}
19 голосов
/ 06 октября 2011

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

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

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

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

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

struct T 
{
    private readonly int u;

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

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

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

4 голосов
/ 06 октября 2011

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

public T(int u) : this() 
{
    this.U = 10;
}
2 голосов
/ 06 октября 2011

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

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

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


}
0 голосов
/ 04 января 2019

С C # 6 это больше не проблема, и она правильно компилируется. Смотрите здесь

...