gpt4 book ai didi

.net - System.Linq.Enumerable.Reverse 是否将所有元素内部复制到数组中?

转载 作者:行者123 更新时间:2023-12-02 13:47:50 25 4
gpt4 key购买 nike

几年前,somebody complained about the implementation of Linq.Reverse() and Microsoft promised to fix that 。那是在2008年,所以问题是,Framework 4是否有Linq.Reverse()的优化实现?当集合类型允许时(例如 IList<T> ),不会具体化集合(即将所有元素复制到内部数组)?

最佳答案

显然不可能优化所有情况。如果某个对象仅实现 IEnumerable<T>而不是IList<T> ,你必须迭代它直到最后找到最后一个元素。因此,优化仅适用于实现 IList<T> 的类型。 (如 T[]List<T> )。

现在,它实际上在 .Net 4.5 DP 中进行了优化吗?让我们启动 Reflector ILSpy:

public static IEnumerable<TSource> Reverse<TSource>(
this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return ReverseIterator<TSource>(source);
}

好的,ReverseIterator<TSource>() 怎么样?看看?

private static IEnumerable<TSource> ReverseIterator<TSource>(
IEnumerable<TSource> source)
{
Buffer<TSource> buffer = new Buffer<TSource>(source);
for (int i = buffer.count - 1; i >= 0; i--)
{
yield return buffer.items[i];
}
yield break;
}

该迭代器 block 的作用是创建一个 Buffer<T>并向后迭代该集合。我们快到了,什么是 Buffer<T>

[StructLayout(LayoutKind.Sequential)]
internal struct Buffer<TElement>
{
internal TElement[] items;
internal int count;
internal Buffer(IEnumerable<TElement> source)
{
TElement[] array = null;
int length = 0;
ICollection<TElement> is2 = source as ICollection<TElement>;
if (is2 != null)
{
length = is2.Count;
if (length > 0)
{
array = new TElement[length];
is2.CopyTo(array, 0);
}
}
else
{
foreach (TElement local in source)
{
if (array == null)
{
array = new TElement[4];
}
else if (array.Length == length)
{
TElement[] destinationArray = new TElement[length * 2];
Array.Copy(array, 0, destinationArray, 0, length);
array = destinationArray;
}
array[length] = local;
length++;
}
}
this.items = array;
this.count = length;
}

// one more member omitted
}

我们这里有什么?我们将内容复制到数组中。在每种情况下。唯一的优化是,如果我们知道 Count (也就是说,集合实现了 ICollection<T> ),我们不必重新分配数组。

因此,对 IList<T> 的优化在 .Net 4.5 DP 中。它在每种情况下都会创建整个集合的副本。

如果我要猜为什么它没有优化,请阅读 Jon Skeet's article on this issue 后,我认为这是因为优化是可观察到的。如果您在迭代时改变集合,您将看到经过优化的更改后的数据,但没有经过优化的旧数据。由于向后兼容性,实际上以微妙的方式改变某些行为的优化是一件坏事。

关于.net - System.Linq.Enumerable.Reverse 是否将所有元素内部复制到数组中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9337284/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com