Допустим, у меня есть класс
public class MyObject
{
public int SimpleInt{get;set;}
}
И у меня есть List<MyObject>
, и я ToList()
это, а затем изменить один из SimpleInt
, будут ли мои изменения будут распространены обратно в первоначальный список. Другими словами, каков будет результат следующего метода?
public void RunChangeList()
{
var objs = new List<MyObject>(){new MyObject(){SimpleInt=0}};
var whatInt = ChangeToList(objs );
}
public int ChangeToList(List<MyObject> objects)
{
var objectList = objects.ToList();
objectList[0].SimpleInt=5;
return objects[0].SimpleInt;
}
Зачем?
P / S: Извините, если кажется очевидным выяснить. Но сейчас у меня нет компилятора ...
.ToList()
сделать мелкую копию. Ссылки копируются, но новые ссылки по-прежнему указывают на те же экземпляры, на которые указывают исходные ссылки. Когда вы думаете об этом,ToList
не можете создать что-либо,new MyObject()
когдаMyObject
естьclass
тип.Ответы:
Да,
ToList
создаст новый список, но поскольку в этом случаеMyObject
это ссылочный тип, то новый список будет содержать ссылки на те же объекты, что и исходный список.Обновление
SimpleInt
свойства объекта, на который есть ссылка в новом списке, также повлияет на эквивалентный объект в исходном списке.(Если
MyObject
было объявлено,struct
а не как,class
то новый список будет содержать копии элементов в исходном списке, и обновление свойства элемента в новом списке не повлияет на эквивалентный элемент в исходном списке.)источник
List
структур структура присваивания, какobjectList[0].SimpleInt=5
, не допускается (ошибка компиляции C #). Это связано с тем, что возвращаемое значение методаget
доступа индексатора списка не является переменной (это возвращаемая копия значения структуры), и поэтому установка его члена.SimpleInt
с помощью выражения присваивания недопустима (это приведет к изменению копии, которая не сохраняется). , Ну, кто использует изменяемые структуры в любом случае?foreach (var s in listOfStructs) { s.SimpleInt = 42; }
. Действительно неприятный глюк, когда вы пытаетесь что - то вродеlistOfStructs.ForEach(s => s.SimpleInt = 42)
: компилятор позволяет это и код работает без исключений, но в Структурах списка останутся без изменений!Из источника Reflector'd:
Так что да, ваш первоначальный список не будет обновляться (то есть, добавления или удаления), как и ссылочные объекты.
источник
ToList
всегда будет создавать новый список, который не будет отражать любые последующие изменения в коллекции.Тем не менее, он будет отражать изменения в самих объектах (если они не изменяемые структуры).
Другими словами, если вы замените объект в исходном списке другим объектом,
ToList
он все равно будет содержать первый объект.Однако если вы измените один из объектов в исходном списке,
ToList
он все равно будет содержать тот же (измененный) объект.источник
Принятый ответ правильно отвечает на вопрос ОП на основании его примера. Тем не менее, он применяется только тогда, когда
ToList
применяется к конкретной коллекции; он не сохраняется, когда элементы исходной последовательности еще не созданы (из-за отложенного выполнения). В последнем случае вы можете получать новый набор предметов при каждом вызовеToList
(или перечислять последовательность).Вот адаптация кода OP, чтобы продемонстрировать это поведение:
Хотя приведенный выше код может показаться надуманным, такое поведение может проявляться как незначительная ошибка в других сценариях. Смотрите мой другой пример для ситуации, когда это вызывает задачи, которые будут порождаться неоднократно.
источник
Да, это создает новый список. Это по замыслу.
Список будет содержать те же результаты, что и исходная перечисляемая последовательность, но материализован в постоянную (в памяти) коллекцию. Это позволяет использовать результаты несколько раз без затрат на повторный расчет последовательности.
Прелесть LINQ-последовательностей в том, что они компонуются. Часто
IEnumerable<T>
вы получаете результат объединения нескольких операций фильтрации, упорядочения и / или проецирования. Методы расширения, такие какToList()
и,ToArray()
позволяют преобразовывать вычисленную последовательность в стандартную коллекцию.источник
Создается новый список, но элементы в нем являются ссылками на оригинальные элементы (как в первоначальном списке). Изменения в самом списке являются независимыми, но элементы найдут изменения в обоих списках.
источник
Просто наткнулся на этот старый пост и подумал добавить два моих цента. Обычно, если у меня есть сомнения, я быстро использую метод GetHashCode () для любого объекта, чтобы проверить идентичность. Так что для выше -
И ответь на моей машине -
Таким образом, по существу, объект, который несет список, остается таким же в приведенном выше коде Надеюсь, что подход поможет.
источник
Я думаю, что это равносильно тому, чтобы спросить, делает ли ToList глубокую или поверхностную копию. Поскольку ToList не имеет возможности клонировать MyObject, он должен делать поверхностную копию, поэтому созданный список содержит те же ссылки, что и исходный, поэтому код возвращает 5.
источник
ToList
создаст новый список.Если элементы в списке являются типами значений, они будут непосредственно обновлены, если они являются ссылочными типами, любые изменения будут отражены обратно в ссылочных объектах.
источник
В случае, когда исходный объект является истинным IEnumerable (т. Е. Не просто коллекцией, упакованной как перечисляемая), ToList () НЕ может возвращать те же ссылки на объекты, что и в исходном IEnumerable. Он вернет новый список объектов, но эти объекты могут не совпадать или даже не совпадать с объектами, полученными IEnumerable при его повторном перечислении
источник
Это также обновит исходный объект. Новый список будет содержать ссылки на объекты, содержащиеся в нем, так же, как исходный список. Вы можете изменить элементы либо, и обновление будет отражено в другом.
Теперь, если вы обновите список (добавление или удаление элемента), который не будет отражен в другом списке.
источник
Я не вижу в документации нигде, чтобы ToList () всегда гарантированно возвращал новый список. Если IEnumerable является списком, может быть более эффективно проверить это и просто вернуть тот же список.
Беспокойство заключается в том, что иногда вам может потребоваться быть абсолютно уверенным, что возвращенный список соответствует исходному списку! Поскольку Microsoft не документирует, что ToList вернет новый список, мы не можем быть уверены (если кто-то не найдет эту документацию). Это может также измениться в будущем, даже если это работает сейчас.
new List (IEnumerable enumerablestuff) гарантированно возвращает новый список. Я бы использовал это вместо этого.
источник
ToList
кажется, что он создает новую ссылку на объект списка при вызовеList
, BenB прав, когда говорит, что это не гарантируется документацией MS.IEnumerable<>.ToList()
фактически реализован как,new List<>(source)
и для него нет специального переопределенияList<>
, поэтомуList<>.ToList()
действительно возвращает новую ссылку на объект списка. Но, опять же, в соответствии с документацией MS, нет никаких гарантий, что это не изменится в будущем, хотя это, скорее всего, повредит большую часть кода.