【发布时间】:2015-06-12 06:45:14
【问题描述】:
我需要将现有列表克隆到另一个现有列表中。由于环境要求非常高的性能,我需要消除不必要的内存重新分配。
我能想到的最有效的算法如下,它将根据需要增加目标列表的容量以匹配源列表,但不会减少自己的容量。 (此项目可接受的行为。)
public static void CloneInto(this List<T> source, List<T> destination)
{
if (destination.Capacity < source.Capacity)
{
/* Increase capacity in destination */
destination.Capacity = source.Capacity;
}
/* Direct copy of items within the limit of both counts */
for (var i = 0; i < source.Count && i < destination.Count; i++)
{
destination[i] = source[i];
}
if (source.Count > destination.Count)
{
/* Append any extra items from source */
for (var i = destination.Count; i < source.Count; i++ )
{
destination.Add(source[i]);
}
}
else if (source.Count < destination.Count)
{
/* Trim off any extra items from destination */
while (destination.Count > source.Count)
{
destination.RemoveAt(destination.Count - 1);
}
}
}
然而这似乎有很多代码、逻辑和循环。
有没有更有效的方法将列表克隆到现有列表中,同时避免不必要的内存分配?
【问题讨论】:
-
你在你的环境中测试过 a.Concat(b) 吗?
-
我不确定 .Concat() 如何适应这个?当 source 有更大的项目时,我想我可以 .Concat() 尾部作为 destination.Concat(source.Skip(destination.Count)) - 这就是你的意思吗?
-
这似乎是函数签名中的错误设计。你确定这是强制性的吗?例如,将
destination.Capacity设置为比当前值更大的值会导致重新分配和复制列表(使用不需要的、立即覆盖的值)。如果签名会返回目标列表,您可以简单地创建一个副本并在容量不够大时返回该列表。 -
您测量/基准测试了吗?这些列表一般有多大?这看起来像是一个不明智的优化。不要把时间花在你没有的问题上。
-
如果原始性能很重要,为什么不放弃
List<T>并使用T[]?运行时直接支持从零开始的一维数组(又名向量),而List<T>是在此基础上构建的类型(因此可能会有一些开销,尽管很小)。
标签: c# performance list memory-management clone