也许这是一个愚蠢的问题...但是创建常量IEnumerable<TSomeType>的最佳方式(在性能和内存方面)是什么?

如果无法定义“最佳”方式,那我有哪些选择?您有什么看法,您认为有最合适的方法吗?

例如:

  • var enumerable = (IEnumerable<TSomeType>) new List<TSomeType> { Value1, Value2, Value3 };
  • var enumerable = (IEnumerable<TSomeType>) new TSomeType[] { Value1, Value2, Value3 };
  • (其他选项;例如Linq Select)。

  • 请考虑内存和性能在这里是一个问题-我们所说的是一个真正受限制的环境(安装了.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/

    10-13 09:32