为什么Reverse for List和IEnumerable有两个完全不同的版本?

对于List对象,我们有一个名为Reverse()的方法。
它反转了“就地”列表的顺序,它不会返回任何内容。

对于IEnumerable对象,我们有一个名为Reverse()的扩展方法。
它返回另一个IEnumerable。

我需要以相反的顺序遍历列表,所以我不能直接使用第二种方法,因为我得到一个List,我不想反转它,只是向后迭代。

所以我可以这样做:

 for(int i = list.Count - 1; i >=0; i--) 

要么

 foreach(var item in list.AsEnumerable().Reverse()) 

我发现它的可读性低于我拥有IEnumerable时的可读性

 foreach(var item in list.Reverse()) 

我无法理解为什么这两种方法以这种方式实现,名称相同。 这很令人讨厌和困惑。

为什么在Reverse()中没有一个名为BackwardsIterator()的扩展名为所有IEnumerable工作?

我对这种选择的历史原因非常感兴趣,而不是“怎么做”的东西!

值得注意的是,list方法比扩展方法要老很多。 命名可能保持不变,因为Reverse似乎比BackwardsIterator更简洁。

如果要绕过列表版本并转到扩展方法,则需要将列表视为IEnumerable

 var numbers = new List(); numbers.Reverse(); // hits list (numbers as IEnumerable).Reverse(); // hits extension 

或者将扩展方法称为静态方法:

 Enumerable.Reverse(numbers); 

请注意, Enumerable版本需要完全迭代底层枚举,以便开始反向迭代。 如果您打算在同一个可枚举项上多次执行此操作,请考虑永久性地颠倒顺序并正常迭代它。

然后编写自己的BackwardsIterator!

 public static IEnumerable BackwardsIterator(this List lst) { for(int i = lst.Count - 1; i >=0; i--) { yield return lst[i]; } } 

不同之处在于List是一个类而IEnumerable是一个接口。 这意味着List对象有一个实现(好吧,它一个实现),并且Reverse的效果保证存储在对象的内部状态中。

使用IEnumerable它是不同的:任何对象都可以实现它,而没有义务实现Reverse方法,因为它不是接口的一部分。 Reverse()扩展方法只能以相反的顺序枚举IEnumerable的枚举IEnumerable ,但永远不会改变主体的内部状态。

但是当Enumerable及其扩展方法被引入时, List.Reverse已经存在。 如果它们是同时发明的, List.Reverse也可能是一种无状态的方法,为了统一性。 谁知道。