使用Enumerable.Empty <T>()而不是新的List <T>()初始化IEnumerable <T>会更好吗?

假设你有一个Person Person:

public class Person { public string Name { get; set;} public IEnumerable<Role> Roles {get; set;} } 

我显然应该在构造函数中实例化angular色。 现在,我曾经这样做过一个列表:

 public Person() { Roles = new List<Role>(); } 

但是我在System.Linq命名空间中发现了这个静态方法

 IEnumerable<T> Enumerable.Empty<T>(); 

来自MSDN :

Empty(TResult)()方法cachingTResulttypes的空序列。 当它返回的对象被枚举时,它不会产生任何元素。

在某些情况下,此方法对于将空序列传递给采用IEnumerable(T)的用户定义方法很有用。 它也可以用来为Union等方法生成一个中性元素。 有关此用法的示例,请参阅示例部分

那么写这样的构造函数会更好吗? 你用它吗? 为什么? 或者如果没有,为什么不呢?

 public Person() { Roles = Enumerable.Empty<Role>(); } 

我认为大多数贴子都没有达到要求。 即使使用空数组或空列表,这些对象也被存储在内存中。 比垃圾收集器必须照顾他们。 如果您正在处理高吞吐量应用程序,可能会造成显着的影响。

Enumerable.Empty不会为每个调用创build一个对象,从而减lessGC的负载。

如果代码处于低吞吐量位置,则归结为审美考虑。

我认为Enumerable.Empty<T>更好,因为它更明确:你的代码清楚地表明你的意图。 它也许会更有效一些,但这只是次要的优势。

假设你实际上想要以某种方式填充Roles属性,然后通过将其设置为private并将其初始化为构造函数中的新列表来封装它:

 public class Person { public string Name { get; set; } public IList<Role> Roles { get; private set; } public Person() { Roles = new List<Role>(); } } 

如果你真的想拥有公共setter,留下值为null Roles并避免对象分配。

在性能方面,让我们看看Enumerable.Empty<T>是如何实现的。

它返回EmptyEnumerable<T>.Instance ,其定义如下:

 internal class EmptyEnumerable<T> { public static readonly T[] Instance = new T[0]; } 

genericstypes上的静态字段是按照genericstypes参数分配的。 这意味着运行时可以只为用户代码需要的types而懒惰地创build这些空数组,并根据需要多次重复使用实例,而不会在垃圾回收器上增加任何压力。

以机智:

 Debug.Assert(ReferenceEquals(Enumerable.Empty<int>(), Enumerable.Empty<int>())); 

你的方法的问题是,你不能添加任何项目的集合 – 我会有一个像列表的私人结构,然后公开项目作为一个枚举:

 public class Person { private IList<Role> _roles; public Person() { this._roles = new List<Role>(); } public string Name { get; set; } public void AddRole(Role role) { //implementation } public IEnumerable<Role> Roles { get { return this._roles.AsEnumerable(); } } } 

如果你打算让其他类创buildangular色列表(我不推荐),那么我不会初始化枚举。

将私有List暴露为IEnumerable的典型问题是,您的类的客户端可能会通过投射来混淆它。 这个代码将工作:

  var p = new Person(); List<Role> roles = p.Roles as List<Role>; roles.Add(Role.Admin); 

你可以通过实现一个迭代器来避免这种情况:

 public IEnumerable<Role> Roles { get { foreach (var role in mRoles) yield return role; } } 

这里面临的更大的问题是将Roles暴露为公共领域

以下看起来更好:

 public class Person { public string Name { get; set; } private List<Role> _roles = null; public IEnumerable<Role> Roles { get { if (_roles != null) return _roles; else return Enumerable.Empty<Role>(); } } } 

也许你应该看看把它作为一个ReadonlyCollection返回,这取决于你想如何使用它。

而Enumerable.Empty在这里并不是better ,当angular色通常保持空白的时候效率更高一点。