为什么有两个完全不同的列表和IEnumerable版本反向的?(Why there is two c

2019-06-28 06:42发布

对于List对象,我们有一个名为方法反向() 。
它扭转列表的顺序“到位”,它不返回任何东西。

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

我需要以相反的顺序throught列表进行迭代,所以我不能直接使用第二种方法,因为我得到一个列表,我不希望扭转这种局面,只是重复倒退。

所以,我可以这样做:

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

要么

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

我发现它比我有一个IEnumerable的可读性,只是做

foreach(var item in list.Reverse())

我不明白为什么这2种方法已经实施这种方式,具有相同的名称。 这是很烦人和混乱。

为什么没有在反向(的地方叫BackwardsIterator())扩展为所有IEnumerable的工作?

我对这个选择的历史原因,比“怎么做”的东西多很感兴趣!

Answer 1:

值得注意的是,该清单方法比扩展方法大很多。 命名很可能保持相同的Reverse似乎比更简洁BackwardsIterator

如果你想绕过列表版本,并转到扩展方法,你需要像对待一个列表IEnumerable<T>

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

或致电扩展方法为静态方法:

Enumerable.Reverse(numbers);

请注意, Enumerable版本将需要完全重复的基本枚举,以便开始反向迭代它。 如果你打算做在同一个枚举此多次,考虑永久扭转秩序和正常迭代它。



Answer 2:

自己写的BackwardsIterator呢!

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


Answer 3:

的存在List<T>.Reverse长之前的存在IEnumerable<T>.Reverse 。 它们被命名为同样的原因是...无能。 这是一个可怕误事; 明确的LINQ IEnumerable<T>函数应该被赋予不同的名称...例如, Backwards ......因为它们具有完全不同的语义。 正因为如此,它奠定了程序员一个可怕的陷阱-有人可能的类型更改list ,从List<T>到,例如, Collection<T>突然list.Reverse(); 的,而不是扭转list到位,简单地返回一个IEnumerable<T>被丢弃。 它不能被夸大了它是多么的无能是MS的给这些方法相同的名称。

为了避免您可以定义自己的扩展方法的问题

public static IEnumerable<T> Backwards<T>(this IEnumerable<T> source) => source.Reverse();

您甚至可以添加可转位名单的高效处理的特殊情况:

public static IEnumerable<T> Backwards<T>(this IEnumerable<T> source) =>
    source is IList<T> list ? Backwards<T>(list) : source.Reverse();

public static IEnumerable<T> Backwards<T>(this IList<T> list)
{
    for (int x = list.Count; --x >= 0;)
        yield return list[x];
}


文章来源: Why there is two completely different version of Reverse for List and IEnumerable?