2013-10-10 3 views
1

Есть ли конструкция языка C#, которая позволит мне добавлять элементы в свойство только для чтения в конструкторе? Я хочу сделать что-то вроде этого:Добавить в сборку readonly в конструкторе?

public class Node{ 
    public IList<Node> Children {get; protected set;} 
    public Node(){ 
     Children = new ObservableList<Node>(); 
    } 
} 

... в моем коде где-то ...

var node = new Node {Children.Add(new Node())}; 

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

UPDATE

OK жаль, что я должен быть более четким. Я не писал этот класс Node, и я не могу его изменить. Я спрашиваю, есть ли концепция языка C#, которая позволит мне добавить к сборке readonly в конструкторе без параметров во втором фрагменте, если класс Node не изменен.

+1

Скрытие 'set' не делают коллекции неизменны , если вы можете получить ссылку на IList, вы можете вызвать «Добавить» на нем. –

+1

Ключевое слово 'readonly' применяется только к полям, а не к свойствам. Он также защищает только поле, а не объект, на который он ссылается. Поэтому добавление 'readonly' в ObservableCollection не приведет к фактической коллекции только для чтения, а только к полю, которое ссылается на нее. – Chris

+1

@ Крис да, я избавился от этого ... это то, что я получаю от «кодирования с бедра» ... –

ответ

4

Попробуйте это. Это, безусловно, можно добавить элементы на строительство

var node = new Node 
{ 
    Children = 
    { 
     new Node(), 
     new Node() 
    } 
}; 
+0

, но свойство 'Children' не предоставляет публичный сеттер, поэтому вызывающий не может назначить новую коллекцию этому свойству. – Servy

+0

@Servy Попробуй, это работает. ему не нужен публичный сеттер. –

+0

Спасибо, именно то, что я искал. –

0

Если у вас есть свойство типа List, то есть get, это означает, что вы не можете установить это свойство, вы все равно можете добавить что-то в список.

Вместо этого вы можете выставить свойство IEnumerable и иметь конструктор, который имеет список (или другой вариант IEnumerable).

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

Я хотел бы сделать это:

public class Node{ 
    public IEnumerable<Node> Children {get; private set;} 
    public Node(IEnumerable<Node> children){ 
     Children = children.ToList(); 
    } 
} 

, если вы не можете изменить Node класс, я предлагаю писать вспомогательный класс, похожий на этот:

public static Node Create(IEnumerable<Node> children) 
{ 
    var n = new Node(); 
    foreach (var c in children) 
     n.Children.Add(c); 
    return n; 
} 
+0

Ну, я действительно не писал класс «Node». Я ссылаюсь на него выше, чтобы указать, как он выглядит снаружи. Я просто создаю экземпляр класса, и почти в каждом экземпляре есть несколько дочерних узлов, которые я также должен создавать. Я надеялся на хорошую конструкцию языка в конструкторе, которая позволила бы мне заставить его работать в одном заявлении. –

-1

Вы можете добавить поле поддержки для свойства «Дети», а затем просто заполнить фоновое поле во время строительства.

Как так

public class Node 
     { 
      private IList<Node> _Children; 
      public IList<Node> Children { get { return _Children; } } 
      public Node(IList<Node> children) 
      { 
       _Children = children; 
      } 
     } 

Тогда вы можете сделать это

var node = new Node((new ObservableList<Node>()).Add(new Node())); 
+0

Скомпилирует? –

+0

Класс да, вызов я не уверен, он действительно должен передать коллекцию в качестве параметра. Возможно, нет, мне пришлось удалить значение по умолчанию. – Smeegs

+0

Я удалил значение по умолчанию из конструктора и скомпилировал его. Ответ был обновлен. – Smeegs

0

Чтобы использовать синтаксис коллекции инициализатора от вас второй фрагменте кода ваш класс Node должен реализовывать IEnumerable и иметь открытый метод с подписью

void Add(Node child) 

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

public class Node 
{ 
    public readonly IEnumerable<Node> Children; 

    public Node(IEnumerable<Node> children) 
    { 
    Children = children; 
    } 
} 

или, если вам не нравится отложенное выполнение IEnumerable:

public class Node 
{ 
    public readonly ReadOnlyCollection<Node> Children; 

    public Node(IEnumerable<Node> children) 
    { 
    Children = new ReadOnlyCollection<Node>(children); 
    } 
} 
Смежные вопросы