Вопрос по c#, .net, constructor, automatic-properties – Автоматически реализованное свойство в структуре не может быть назначено

24

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

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

    public int U { get; private set;  }
}

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

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

Ваш Ответ

5   ответов
2

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

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

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


}
19

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

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

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; } }
}

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

@ Praetor12: Ну, вы могли бы прочитать рекомендации по проектированию для разработчиков библиотек классов:msdn.microsoft.com/en-us/library/ms229042.aspx - это будет включатьнесколько из этого материала, но не все. Jon Skeet
Все, что я хочу сделать, вы называете «плохим дизайном» :( Есть ли для него какие-то правила? Vasya
Стоит получить некоторый материал для чтения, чтобы подкрепить ваши знания. Мои две верхние рекомендации - «Руководства по проектированию фреймворка: условные обозначения, идиомы и шаблоны для многократно используемых библиотек .NET» от Cwalina и Abrams, а также собственное «C # in the Depth» г-на Скита. Понимание лучших практик фреймворка приходит с опытом, когда вы начнете понимать не только то, что делает ваш код, но также и то, как это влияет на другие части вашего кода, вы начнете развивать то, как вы пишете код, естественно, и, надеюсь, начнете использовать лучшие практики, где вы можете. Matthew Abbott
73

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

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

[Исключен]

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

[Исключен]

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

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

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

    public int U { get; private set; }
}
из C # 6 вам не нужно добавлять:this() ES2018
Да, эти детали драгоценны. Теперь я все это знаю. Благодарю. Vasya
+1 за дополнительную детализацию. Jeffrey Hantin
4

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

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

и она правильно компилируется. СмотретьВот

Похожие вопросы