.NET Почему IEnumerable.ToList () в существующем списке создает новый массив - PullRequest
7 голосов
/ 29 ноября 2011

Просто из любопытства, почему вызов IEnumerable.ToList () в существующем списке не возвращает тот же экземпляр?То же относится и к IEnuerable.ToArray ().Разве это не будет лучше с точки зрения потребления памяти?

Я провел следующий быстрый тест:

  var things= new List<Thing>( new [] {new Thing(), new Thing()});
        Console.WriteLine(things.GetHashCode());

        things= things.ToList();
        Console.WriteLine(things.GetHashCode());

И я получаю разные экземпляры объектов.Почему не просто такие же экземпляры?

Ответы [ 3 ]

9 голосов
/ 29 ноября 2011

Это сделано специально для включения сценария «список копирования».

Например, если я сделаю foreach( var a in list ) list.Remove(a), я получу исключение, говорящее, что «коллекция была изменена», в то время какПеречисление было в процессе.

Чтобы это исправить, я делаю: foreach( var a in list.ToList() ) list.Remove(a).

Если вы хотите семантику в духе «преобразовать в список, если она еще не одна», выПридется справиться самому.Фактически, вы могли бы написать для этого аккуратный метод расширения:

public static IList<T> ToListIfNotAlready( this IEnumerable<T> source )
{
     var list = source as IList<T>;
     return list == null ? source.ToList() : list;
}

Да, могло быть и наоборот, но разработчики LINQ выбрали этот подход и имели полное право сделать это,поскольку ни один из подходов не имеет явного преимущества в общем случае.

1 голос
/ 29 ноября 2011

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

0 голосов
/ 30 апреля 2015

Поведение ToList () не имеет ничего общего с перечислением. Он делает то, что подразумевает имя, то есть возвращает список. Это не значит, что он возвращает один и тот же список при каждом вызове; иначе; Экземпляр списка должен храниться где-то внутри. То же самое со многими другими функциями Linq. Тот факт, что он возвращает новый список, полезен для использования с перечислителем foreach.

...