поля readonly как цели из конструкторов подкласса - PullRequest
19 голосов
/ 10 октября 2011

Поле «только для чтения» следует использовать, когда у вас есть переменная, которая будет известна при установке объекта, которая не должна изменяться впоследствии.

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

У кого-нибудь есть хорошее объяснение, почему это либо не очень хорошая идея, либо отсутствует язык C #?

abstract class Super
{
    protected readonly int Field;
}

class Sub : Super 
{
    public Sub()
    {
        this.Field = 5; //Not compileable
    }
}

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

Ответы [ 5 ]

12 голосов
/ 10 октября 2011

Единственная причина, по которой я это вижу, заключается в том, что «он был спроектирован именно так», согласно spec :

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

Смысл использования только для чтения в том, что его нельзя изменить, если производные классы могут измениться, это больше не будет истинным и нарушит инкапсуляцию (изменяя внутренние компоненты другого класса).

10 голосов
/ 10 октября 2011
public class Father
{
    protected readonly Int32 field;

    protected Father (Int32 field)
    {
        this.field = field;
    }
}

public class Son : Father
{
    public Son() : base(5)
    {

    }
}

Вместо этого вы можете попробовать что-то подобное!

1 голос
/ 10 октября 2011

Я бы смоделировал это с помощью абстрактного / виртуального свойства в C #.

abstract class Super {
  protected abstract int Field { get; }
}

class Sub : Super {
  protected override int Field { get { return 5; } }
}

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

class Sub : Super {
  public Sub() : base(5) { } // 5 what ?? -> need to check definition of super class constructor
}

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

0 голосов
/ 11 апреля 2012

Я бы предпочел использовать защищенный конструктор в суперклассе (как упомянуто alexm), а также в комментариях xml.Это должно устранить проблему, о которой ДонАндре сказал в своем комментарии к коду.

0 голосов
/ 10 октября 2011

Полагаю, основная причина - дополнительная сложность для всех реализаций языка .NET

также всегда существует простой обходной путь:

 abstract class Super
 {
     protected readonly int Field;

     protected Super(int field)
     {
          this.Field = field;
     }
 }


class Sub : Super {
   public Sub():base(5)
   {
   }

}

...