Ошибка компиляции. Использование свойств со структурой - PullRequest
12 голосов
/ 02 декабря 2010

Пожалуйста, объясните следующую ошибку в конструкторе структуры. Если я изменю структуру на класс ошибки исчезли.

public struct DealImportRequest
{
    public DealRequestBase DealReq { get; set; }
    public int ImportRetryCounter { get; set; }

    public DealImportRequest(DealRequestBase drb)
    {
        DealReq = drb;
        ImportRetryCounter = 0;
    }
}
  • ошибка CS0188: объект 'this' нельзя использовать, пока все его поля не присвоены
  • ошибка CS0843: вспомогательное поле для автоматически реализуемого свойства 'DealImportRequest.DealReq' должен быть полностью назначен до того, как управление будет возвращено вызывающей стороне. Попробуйте вызвать конструктор по умолчанию из инициализатора конструктора.

Ответы [ 3 ]

14 голосов
/ 02 декабря 2010

Как рекомендует сообщение об ошибке, вы можете решить эту проблему, вызвав конструктор по умолчанию из инициализатора конструктора.

public DealImportRequest(DealRequestBase drb) : this()
{
   DealReq = drb;
   ImportRetryCounter = 0;
}

Из спецификации языка:

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

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

Другой (более подробной) альтернативой, конечно, является ручная реализация свойств и установка собственных полей в конструкторе.

Обратите внимание, что у вас есть изменяемая структура. Это не рекомендуется . Я предлагаю вам либо сделать тип классом (проблемы с компиляцией должны исчезнуть немедленно), либо сделать тип неизменяемым. Самый простой способ сделать это, предполагая, что представленный вами код - это структура whole , - сделать установщики частными (get; private set;). Конечно, вы также должны убедиться, что впоследствии вы не добавляете в структуру никакие мутирующие методы, которые полагаются на частный доступ для изменения полей. Кроме того, вы можете создать резервные копии свойств с помощью readonly полей поддержки и вообще избавиться от сеттеров.

3 голосов
/ 02 декабря 2010

Код, который у вас есть, эквивалентен следующему коду:

public struct DealImportRequest
{
    private DealRequestBase _dr;
    private int _irc;
    public DealRequestBase DealReq
    {
      get { return _dr; }
      set { _dr = value; }
    }
    public int ImportRetryCounter
    {
      get { return _irc; }
      set { _irc = value; }
    }
    /* Note we aren't allowed to do this explicitly - this is didactic code only and isn't allowed for real*/
    public DealImportRequest()
    {
        this._dr = default(DealRequestBase); // i.e. null or default depending on whether this is reference or value type.
        this._irc = default(int); // i.e. 0
    }
    public DealImportRequest(DealRequestBase drb)
    {
        this.DealReq = drb;
        this.ImportRetryCounter = 0;
    }
}

Теперь все, что я сделал здесь, это удалил синтаксический сахар, который:

  1. Реализует автоматические свойства.
  2. Определяет, с какими членами обращаются относительно this.
  3. Предоставляет все struct sa конструктор по умолчанию без параметров.

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

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

Это комбинация различных автоматических функций, о которых нам обычно не нужно думать, но в этом случаене работает хорошоМы можем исправить это, следуя совету в сообщении об ошибке для 843 и вызывая конструктор по умолчанию как часть вашего явного конструктора:

public DealImportRequest(DealRequestBase drb)
    :this()
{
    DealReq = drb;
    ImportRetryCounter = 0;
}

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

0 голосов
/ 09 июня 2014

Я бы рекомендовал не использовать авто-свойства со структурами, если у вас нет веских причин использовать их.Обертывание поля класса в свойстве чтения-записи полезно, поскольку оно позволяет экземпляру управлять обстоятельствами, когда он может быть прочитан или записан, и предпринимать действия, когда происходит чтение или запись.Кроме того, код в экземпляре объекта может идентифицировать экземпляр, на который воздействуют, и, таким образом, может выполнять специальное действие только при чтении и записи конкретного экземпляра.Использование автоматического свойства в более ранней версии класса позволит будущим версиям класса использовать свойство, реализованное вручную, включая вышеупомянутые преимущества, при сохранении совместимости с уже скомпилированным клиентским кодом.К сожалению, обертывание поля структуры в свойстве чтения-записи не дает тех же преимуществ, поскольку поля одного экземпляра структуры могут быть скопированы в другой, причем ни один экземпляр не имеет права голоса в этом вопросе.Если семантика структуры позволяет в большинстве случаев записывать свойство с произвольными значениями [как в случае с авто-свойством], то любая законная замена будет семантически эквивалентна полю.

...