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

Cyr*_*don 29 c# linq ienumerable reverse list

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

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

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

所以我可以这样做:

for(int i = list.Count - 1; i >=0; i--)
Run Code Online (Sandbox Code Playgroud)

要么

foreach(var item in list.AsEnumerable().Reverse())
Run Code Online (Sandbox Code Playgroud)

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

foreach(var item in list.Reverse())
Run Code Online (Sandbox Code Playgroud)

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

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

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

Ada*_*rth 23

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

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

var numbers = new List<int>();
numbers.Reverse(); // hits list
(numbers as IEnumerable<int>).Reverse(); // hits extension
Run Code Online (Sandbox Code Playgroud)

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

Enumerable.Reverse(numbers);
Run Code Online (Sandbox Code Playgroud)

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

  • 实际上,即使一个人只想要枚举一次并想保持原始列表不受干扰,我希望调用`ToArray()`然后调用`Reverse()`几乎肯定会更快.结果数组,而不是使用`Enumerable.Reverse()`.`List <T> .ToArray()`方法可以将数据作为块存储在目标数组中,而不必处理单个项目,而`Enumerable.Reverse()`将 - 除非它具有特殊处理的情况下source是一个`List <T>` - 在将它们反转之前,一次一个地将项目复制到一个数组中. (2认同)

Ani*_*dha 5

然后编写您自己的BackwardsIterator!

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

  • 如果要使用实用程序方法,则应使用更有效的方法(即,反向for循环)。作为IEnumerable的`Reverse`效率很低,因为它需要迭代可枚举的对象,将其存储在缓冲区中,然后反向迭代该缓冲区。 (2认同)