Назначение значения унаследованному полю только для чтения? - PullRequest
25 голосов
/ 18 мая 2011

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

Свойства / поля, доступные только для чтения, позволяют изменять значение переменной внутри конструктора, а также определение, но больше нигде. Я получаю ошибку «только для чтения, которая может быть назначена только в конструкторе», если я пытаюсь изменить значение унаследованной переменной «только для чтения» в конструкторе дочернего класса. Почему это так и как я могу обойти это без отражения?

Мое намерение: разрешить расширяемость пользователя с помощью сценариев, где они могут изменять только определенные поля один раз.

Ответы [ 5 ]

23 голосов
/ 18 мая 2011

Причина в том, что вы можете назначить только для чтения поля в конструкторе этого класса.
Согласно определение только для чтения в C # Reference (выделено мной):

Когда объявление поля включает модификатор readonly, присваивания полям, введенным объявлением, могут происходить только как часть объявления или в конструкторе того же класса .

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

Пример:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Base b = new Child();
            Console.WriteLine(b.i);
            Console.Read();
        }
    }

    class Base
    {
        public readonly int i;

        public Base()
        {
            i = 42;
        }

        protected Base(int newI)
        {
            i = newI;
        }
    }

    class Child : Base
    {
        public Child()
            : base(43)
        {}
    }
}
8 голосов
/ 18 мая 2011

Адам имеет правильный ответ.Если вас беспокоит пространство, которое оно займет (количество параметров в конструкторе?), То вам следует решить эту проблему как другую проблему с другим решением: создать класс BaseConfig, который содержит все эти свойства и это все, чтодолжен быть передан. Base может затем либо назначить все свои поля только для чтения из свойств BaseConfig, либо вместо этого можно использовать Base для хранения только одного поля только для чтения типа BaseConfig и обратиться к нему для значений.см. порядок выполнения конструктора C # относительно того, когда поля каждого класса только для чтения будут инициализированы / инициализированы.

8 голосов
/ 18 мая 2011

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

public class BSE
{
    virtual public int Prop 
    {
        get
        {
            return 6;
         }
     }
}
public class Derived : BSE
{
    public override int Prop
    {
         get
         {
             return 10;
         }
    }
 }

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

3 голосов
/ 28 февраля 2015

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

Пример:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Base b = new Child();
            Console.WriteLine(b.I);
            Console.Read();
        }
    }

    class Base
    {
        public int I { get; protected set; }

        public Base()
        {
            I = 42;
        }
    }

    class Child : Base
    {
        public Child()
        {
            I = 43;
        }
    }
}
0 голосов
/ 18 мая 2011

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

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