2017-01-02 3 views
1

Я новичок в C# (первое сообщение) и в настоящее время работает над проблемой «инкапсуляции». В принципе у меня есть два класса, как это (упрощенный):Очистить property- (public) Список, не снимающий личный список (новичок)

class Myclass 
    { 

     private List<X> _list; 
     public List<X> list 
     { 
      get 
      { 
       return _list; 
      } 
     } 
     ... 
     public Myclass (List<X> input) 
     { 
      _list = new List <X>(input); 
     } 
     ... 
    } 

class Testclass 
    { 
     List<X> inputList = new List<X>() {"bla", "bla"}; 
     Myclass myclass = new Myclass(inputlist); 

     myclass.list.Clear(); 
     List<X> newL = myclass.list; 
    } 

Я не должен ничего менять со второго класса «TestClass».

И это моя проблема: myclass.list.Clear() очищает публичный список И частный список. Но я только хочу, чтобы он очистил публичный список или ничего не сделал, потому что в конце мне нужен список newL, который должен быть заполнен элементами из частного списка (открытый список через get-accessor).

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

Как я уже сказал, я довольно плохой/новый в программировании в целом (19 лет), поэтому приветствуются новички-ответы.

ответ

2
public List<X> list 
{ 
    get 
    { 
     return new List<X>(_list); 
    } 
} 

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

Пожалуйста, обратите внимание, что в реальном коде производства вы бы вместо того, чтобы изменить свойство не возвращать список, но что-то, что просто не имеют опцию, чтобы изменить его (как IEnumerable<T>). Предоставление кому-то Список, а затем игнорирование того, что он делает с ним, очень неинтуитивно для вызывающего и не совсем хорошего программирования.

+0

Отличный ответ, насколько я понимаю. Полностью имеет смысл. Большое спасибо, я проведу его через секунду :) <3 –

+1

Вы также можете использовать 'return _list.ToList()' вместо нового конструктора (я не знаю, какой из них наиболее эффективен) – fharreau

+1

@fharreau Поскольку '.ToList()' делает [точно так же] (https://github.com/Microsoft/references/source/blob/master/System.Core/System/Linq/Enumerable.cs#L835) как мою строку кода, использование конструктора списка можно рассматривать как незначительно более эффективное (сохранение нулевой проверки). Поскольку это не тот уровень эффективности, о котором стоит позаботиться, используйте то, что лучше читает. – nvoigt

1

Когда список доступен через ваше свойство, это экземпляр списка, который хранится в вашем (backing-) поле, поэтому оба списка являются одним и тем же объектом. Вот почему ваш Clear вызывается в поле. Для того, чтобы доставить список в пути только для чтения, у вас есть две возможности:

  • Вы можете клонировать список: Таким образом, возвращаемый список не тот же объект, но имеет те же элементы, как первоначальный список. Пример: return _list.ToList(); или return new List(_list);

  • Вы можете использовать ReadOnlyCollection<T>. Это, как указано в названии, только для чтения, поэтому никто не может добавлять или удалять элементы.

+0

Спасибо за ваш ответ! Это работает! <3 Ответ подобен тому, что nvoigt. Еще большое спасибо! –

Смежные вопросы