Изменение переменной изменяет также другую переменную. Запретить переменным иметь одну и ту же ссылку

#c# #pass-by-reference #pass-by-value

#c# #передача по ссылке #передача по значению

Вопрос:

У меня есть класс, для которого конструктору требуется класс, и другие вещи, такие как:

 public class SomeClass<T>
{
    //global private variables for class
    List<T> originalList = new List<T>;
    List<T> tempList = new List<T>;

    public SomClass(List<T> listParam, string name, ..etc)
    {
        originalList = listParam;
        tempList = listParam;

        originalList.removeAt(0);  // this also removes an item from tempList.


    }
}
  

Я знаю, это потому, что originalList и tempList имеют одну и ту же ссылку. Как я мог бы заставить их иметь разные ссылки. Я использую tempList для фильтрации результатов, и всякий раз, когда я хочу обновить, я использую originalList

Ответ №1:

Вы могли бы сделать копию listParam , а не просто назначать ее ссылку:

 tempList = listParam.ToList();
  

Обратите внимание, что это не создает копию каждого объекта в списке, а просто копию ссылок на эти объекты.

Ответ №2:

Вместо принятия a List<T> , примите IEnumerable<T> . Если затем вам нужен конкретный список, вызовите .ToList() для него.

Исходный источник не затронут, и у вас есть копия. У вас также есть преимущество в том, что вы можете использовать все, что поддерживает интерфейс.

Редактировать: я неправильно прочитал код в вопросе, ваша копия находится в том же классе. Ну, это в двух местах, в классе и вызывающем объекте. Я придерживаюсь своего предложения, но да, вам понадобятся два вызова .ToList() , по одному для каждой копии.

Комментарии:

1. «Вместо того, чтобы принимать список<T>, примите IEnumerable<T>» — есть ли причина сделать это, когда ему конкретно нужен список?

2. @zerkms, в интересах большей поддержки в классе. Он поддерживает любую последовательность типа T, это не обязательно должна быть конкретная реализация. Если все, что он когда-либо хотел поддерживать, — это конкретную реализацию, у него есть такая возможность. Но использование интерфейса с наименьшими ограничениями просто дает ему больше возможностей, вот и все.

3. Да, предоставляет больше возможностей и требует копировать список каждый раз (даже когда нам не нужна копия и список значительно большой) 😉

4. @zerkms, ему все равно придется скопировать список в соответствии с его требованием. Но, да, для поддержки двух независимых списков в своем классе он скопировал бы его дважды, используя этот подход. Однако, если он хочет, чтобы список в источнике оставался независимым, ему все равно нужно это сделать.