Подтвердить что ты не робот

Readonly-fields в качестве целей от конструкторов подкласса

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

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

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

abstract class Super
{
    protected readonly int Field;
}

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

public class Father
{
    protected readonly Int32 field;

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

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

    }
}

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

Ответ 3

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

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

 abstract class Super
 {
     protected readonly int Field;

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


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

}

Ответ 4

Я бы моделировал это абстрактно/виртуальным свойством в С#.

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

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

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

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

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

Ответ 5

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