Почему IList‹›.Reverse() не работает как List‹›().Reverse

У меня проблема с List<T>.Reverse() и Reverse(this IEnumerable<TSource> source). Посмотрите на код:

  // Part 1
  List<int> list = new List<int> { 1, 2, 3 };

  foreach (int x in list)
    Console.Write(x);

  Console.WriteLine();

  list.Reverse();

  foreach (int x in list)
    Console.Write(x);

  Console.WriteLine();
  list.Reverse();

  // Part2
  IList<int> ilist = list;

  foreach (int x in list)
    Console.Write(x);      

  Console.WriteLine();

  ilist.Reverse();

  foreach (int x in ilist)
    Console.Write(x);

  Console.WriteLine();

  ilist.Reverse();

Мой результат:

123
321
123
123

потому что Reverse()-Часть 1 – это List<T>.Reverse(), Reverse() – Часть 2 – это Reverse(this IEnumerable<TSource> source). Я хочу выполнить List<int>.Reverse() в Части 2 для IList<int>. Как я могу это сделать?


person AndreyAkinshin    schedule 12.01.2011    source источник
comment
Я согласен с вами, что это сбивает с толку.   -  person Dan Tao    schedule 12.01.2011


Ответы (2)


IList<int> не имеет метода Reverse, поэтому использует метод расширения. Единственный способ использовать List<T>.Reverse в вашем эталоне IList<int> — преобразовать его в List<int>. Кастинг будет работать только в том случае, если вы уверены, что это действительно List<int>:

IList<int> abstractList;
var concreteList = (List<int>)abstractList;
concreteList.Reverse();

Другой вариант — создать экземпляр List<int> из экземпляра IList<int>, а не предполагать, что он уже является экземпляром List<int>:

IList<int> abstractList;
var concreteList = new List<int>(abstractList);
concreteList.Reverse();

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

Чтобы использовать эту версию Reverse, просто используйте результат вызова Reverse, а не исходный список:

IList<int> abstractList;
IEnumerable<int> reversedList = abstractList.Reverse();
person bdukes    schedule 12.01.2011

Во втором примере вы используете метод расширения для IEnumerable<T>, и это не изменение исходной коллекции, а скорее создание запроса, который приведет к последовательности вашего исходного списка в обратном порядке. То есть, если вы хотите использовать результаты ilist.Reverse(), вы должны сказать

var reversedList = iList.Reverse(); 
// reversedList is IEnumerable<int>
// 'list' and 'ilist' are not changed

foreach (int item in reversedList)
    Console.Write(item);
person Anthony Pegram    schedule 12.01.2011
comment
короткий, но лаконичный ответ на поставленный вопрос. Выручил меня. Спасибо +1 - person Moe Howard; 13.03.2012