也许这是一个愚蠢的问题...但是创建常量IEnumerable<TSomeType>
的最佳方式(在性能和内存方面)是什么?
如果无法定义“最佳”方式,那我有哪些选择?您有什么看法,您认为有最合适的方法吗?
例如:
var enumerable = (IEnumerable<TSomeType>) new List<TSomeType> { Value1, Value2, Value3 };
var enumerable = (IEnumerable<TSomeType>) new TSomeType[] { Value1, Value2, Value3 };
请考虑内存和性能在这里是一个问题-我们所说的是一个真正受限制的环境(安装了.NET的小型设备)。
提前致谢。
最佳答案
好吧,List<T>
和数组都不是不可变的,因此,如果您真正追求不可变性,那么它们就不会出现-调用者可以转换结果,然后对其进行修改。
您可以创建一个List<T>
并将其包装在ReadOnlyCollection<T>
中。如果再也没有对原始列表的引用,那么它实际上是不可变的,除非有反射。
如果您实际上并不关心不变性-也就是说,如果您相信所有代码都不会搞乱它,那么几乎可以肯定,数组将是性能最高的方法。有各种CLR级别的优化使它们运行起来非常快。但是,在那种情况下,我不会转换为IEnumerable<T>
-我只是将其公开为数组。与编译器必须调用GetEnumerator()
相比,这将使迭代更快。
如果C#编译器在数组上看到foreach
语句,它将生成直接进入索引器并使用Length
属性的调用……然后CLR也将能够删除边界检查,从而发现模式。
同样,如果您决定使用List<T>
,请将其保留为List<T>
-这样,您将可以直接使用List<T>.Enumerator
-这是一个结构-无需装箱。
编辑:史蒂夫·梅格森为此提出了使用LINQ的观点。实际上,您可能会做得更好,因为一旦获得了基础列表的枚举器,您就可以安全地将其返回给调用者,至少对于我所知道的所有集合而言。因此,您可以:
public class ProtectedEnumerable<T> : IEnumerable<T>
{
private readonly IEnumerable<T> collection;
public ProtectedEnumerable(IEnumerable<T> collection)
{
this.collection = collection;
}
public IEnumerator<T> GetEnumerator()
{
return collection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
这意味着在迭代时只有很少的命中-仅是对
GetEnumerator()
的委派调用。与使用Enumerable.Select
进行比较,使用MoveNext()
时,每次调用ojit_code(以及无操作投影)都需要额外的委托(delegate)命中。关于c# - 创建常量IEnumerable <TSomeType> ...的方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4091451/