Как сделать свойство списка доступным для записи в инициализаторе объекта, но только для чтения в других местах? - PullRequest
0 голосов
/ 23 марта 2020

Рассмотрим следующий фрагмент кода, который не компилируется.

class Class
{
    public double Value { get; set; }
    public int Frequency { get; set; }
}

class BoxAndWhisker
{
    private readonly List<Class> _classes = new List<Class>();
    public BoxAndWhisker()
    {
        Classes = _classes.AsReadOnly();
    }
    public IReadOnlyList<Class> Classes { get; } 

}
class Program
{
    static void Main(string[] args)
    {
        BoxAndWhisker baw = new BoxAndWhisker
        {
            Classes =
            {
                new Class{ Value=1,Frequency=20},
                new Class{Value=2,Frequency=10}
            }
        };
    }
}

Я хочу, чтобы свойство Classes было доступно только для чтения сразу после установки baw. Как это сделать? Другими словами, Classes должен быть доступен для записи в инициализаторе объекта, но только для чтения в других местах.

Редактировать

Я предпочитаю инициализатор объекта параметризованному конструктору.

Ответы [ 4 ]

1 голос
/ 23 марта 2020

Синтаксис "инициализатора объекта" в C# не имеет различий по семантике c по сравнению с назначением значения свойства.

В документах можно прочитать :

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

Итак, это:

var foo = new Bar { Baz = "baz" };

полностью эквивалентен :

var temp = new Bar();
temp.Baz = "baz";
var foo = temp;

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

1 голос
/ 23 марта 2020

Удалите

set;

Из свойств в

Класс

И сделайте в Классе конструктор, который устанавливает начальные значения Свойства, поэтому их нельзя перезаписать / изменить

1 голос
/ 23 марта 2020

Почему бы не передать Class es через конструктор ? Например,

class BoxAndWhisker {
  public BoxAndWhisker(params Class[] items) {
    Classes = null != items
      ? new List<Class>(items).AsReadOnly()
      : throw new ArgumentNullException(nameof(items));
  }

  public IReadOnlyList<Class> Classes { get; }
}

Тогда

static void Main(string[] args) 
{
    BoxAndWhisker baw = new BoxAndWhisker(
        new Class { Value = 1, Frequency = 20 },
        new Class { Value = 2, Frequency = 10 }
    );

    ...
}
1 голос
/ 23 марта 2020

Вы передаете экземпляр IList<Class> конструктору BoxAndWhisker и сохраняете базовое свойство IReadOnlyList<Class>

class BoxAndWhisker
{
    public BoxAndWhisker(IList<Class> classes)
    {
        if (classes == null)
            throw new ArgumentNullException(nameof(classes));

        Classes = new ReadOnlyCollection<Class>(classes);
    }

    public IReadOnlyList<Class> Classes { get; }
}

Пример использования

BoxAndWhisker baw = new BoxAndWhisker(new List<Class>
{
    new Class {Value = 1, Frequency = 20},
    new Class {Value = 2, Frequency = 10}
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...