使用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)()
方法cachingTResult
types的空序列。 当它返回的对象被枚举时,它不会产生任何元素。在某些情况下,此方法对于将空序列传递给采用
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色通常保持空白的时候效率更高一点。