为什么IList<>.Reverse()不能像List<>().Reverse()那样工作?

11

我遇到了 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()-Part1是List<T>.Reverse()Reverse()-Part2是Reverse(this IEnumerable<TSource> source)

我想在Part2中执行List<int>.Reverse()以针对IList<int>。如何做到?


2
我同意你的看法,这确实令人困惑。 - Dan Tao
2个回答

11

IList<int> 没有 Reverse 方法,所以它使用扩展方法。如果要在您的 IList<int> 引用上使用 List<T>.Reverse 的唯一方法是将其强制转换或转换为 List<int>。只有当您确定其首先实际上是 List<int> 时,强制转换才有效:

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

另一个选择是从您的IList<int>实例创建一个List<int>,而不是假设它已经是一个List<int>

IList<int> abstractList;
var concreteList = new List<int>(abstractList);
concreteList.Reverse();
< p > < em > Reverse 扩展方法不会实际影响底层列表的原因是因为它作用于 < code > IEnumerable & lt;T> ,这并不一定是可写的(所有的 < code > Enumerable 扩展方法都不会改变原始集合,它们返回一个 < em > 新 集合)。 < p>要使用这个版本的 < code > Reverse ,只需使用 < code > Reverse 调用的产物,而不是原始列表:

IList<int> abstractList;
IEnumerable<int> reversedList = abstractList.Reverse();

4
在第二个例子中,您正在使用针对 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);

简短而简洁的回答解决了问题。帮了我很大的忙。谢谢 +1 - Moe Howard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接