IEnumerable<T>.Reverse 和 List<T>.Reverse 的区别

9
为什么IEnumerable<T>.Reverse()返回反转的集合和原始集合一样,而List<T>却把原始集合本身反转呢?这对我来说有些困惑,因为List<T>是从IEnumerable<T>继承而来。

1
IEnumerable<T>是一个接口,而List<T>并不继承它,它实现了它。这是一个巨大的区别。 - MarcinJuraszek
6个回答

11
因为它们是两种不同的方法。 List<T>.ReverseList<T> 上的实例方法,这会直接修改该列表。 而Enumerable.Reverse<T>IEnumerable<T> 的扩展方法,它会创建一个新序列,并反向枚举源序列。 你可以将后者作为静态方法调用,并在 List<T> 上使用它。
var list = new List<string>{"1","2"};
var reversed = Enumerable.Reverse(list)

或者通过将其强制转换为 IEnumerable<T>

IEnumerable<string> list = new List<string>{"1","2"};
var reversed = list.Reverse();

在这两种情况下,list保持不变且reversed在枚举时返回{"2","1"}


我添加了一个Extension方法'Reversed',它只是包装了Ienumerable.Reverse - 在很多情况下,你希望实现不可变性,现在你可以直接调用它,无需进行任何转换或其他样板代码。 - Dirk Boer

9
概念上,这可能是因为当您想要表示不可变项目的集合时使用 IEnumerable。也就是说,您只想读取列表中的项目,而不想添加/插入/删除或以其他方式更改集合。在这种数据视图中,返回一个新的以不同顺序排列的 IEnumerable 是预期的结果。当您使用 List 时,您希望能够添加/插入/删除或以其他方式更改集合,因此在该上下文中预期会有一个改变原始列表顺序的 Reverse 方法。

正如其他人已经指出的那样,IEnumerable 是一个接口,而 List 是一个类。 List 实现了 IEnumerable

所以,

 IEnumerable<String> names = new List<String>();
 var reversedNames = names.Reverse();

使用该函数可以得到一个反转后的第二个列表。

而,

 List<String> names = new List<String>();
 names.Reverse(); 

将您原来的列表反转。希望这样说清楚了。


3

IEnumerable<T>Reverse是Linq的一部分,是作为扩展方法添加的(Enumerable.Reverse<T>)。在List<T>实现Reverse之后,它被添加了进来。

IEnumerable<T>也不是对象的集合。它只是告诉消费者如何获取这些项。


看起来这个答案是唯一一个解释“为什么”的答案:“它是在List<T>实现了Reverse之后添加的”。 - Lucas Trzesniewski

0

这些是不同的方法,要记住。本质上是不同的,除了名称外没有任何共同点。

void List.Reverse 是仅适用于 List 实例的方法,它可以就地反转列表或其中一部分。

IEnumerable Enumerable.Reverse 是一个扩展方法(顺便说一下,IList 也有它!),它创建一个新的可枚举对象并将其顺序反转。


0

不存在 IEnumerable<T>.Reverse() 这样的东西。它是 Enumerable.Reverse<T>(this IEnumerable<T>),是 Linq 的扩展方法,适用于所有的 IEnumerable<>

现在我们已经确定它们的来源,很容易理解它们为什么如此不同。Linq 添加了创建“处理流”的方法,通过每次创建新实例来实现。

List<T>.Reverse()List 的一个方法,就像它的所有方法(例如 Add)一样,直接修改实例。


0

IEnumerable<T> 有一个底层实现,可以是 List<T>Hashtable<T> 或其他实现 IEnumerable 的东西。

List<T> 本身就是实现,所以您可以直接修改该实例。

正如其他人提到的,一个是扩展方法和 Linq 的一部分,另一个是直接在类型上实现的。


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