Is it better to use Enumerable.Empty<T>() as opposed to new List<T>() to initialize an IEnumerable<T>?
假设你有一个班上的人:
1 2 3 4 5 | public class Person { public string Name { get; set;} public IEnumerable<Role> Roles {get; set;} } |
显然,我应该实例化构造函数中的角色。现在,我用这样的列表来做:
1 2 3 4 |
但是我在
1 | IEnumerable<T> Enumerable.Empty<T>(); |
来自MSDN:
The
Empty(TResult)() method caches an
empty sequence of typeTResult . When
the object it returns is enumerated,
it yields no elements.In some cases, this method is useful
for passing an empty sequence to a
user-defined method that takes an
IEnumerable(T) . It can also be used to
generate a neutral element for methods
such asUnion . See the Example section
for an example of this use of
那么,这样编写构造函数更好吗?你用它吗?为什么?或者如果没有,为什么不呢?
1 2 3 4 | public Person() { Roles = Enumerable.Empty<Role>(); } |
我认为大多数帖子都没有抓住要点。即使使用空数组或空列表,它们也是对象,并存储在内存中。比垃圾收集者还要照顾他们。如果您处理的是高吞吐量应用程序,那么它可能会受到显著的影响。
如果代码处于低吞吐量位置,那么它归根结底就是美学上的考虑。
我认为
在性能方面,我们来看看
返回
1 2 3 4 |
泛型类型上的静态字段是按泛型类型参数分配的。这意味着运行时可以仅为用户代码需要的类型而延迟地创建这些空数组,并且可以根据需要多次重用实例,而不会对垃圾收集器施加任何压力。
才智:
1 | Debug.Assert(ReferenceEquals(Enumerable.Empty<int>(), Enumerable.Empty<int>())); |
假设您实际上想以某种方式填充
1 2 3 4 5 6 7 8 9 10 | public class Person { public string Name { get; set; } public IList<Role> Roles { get; private set; } public Person() { Roles = new List<Role>(); } } |
如果您真的想拥有公共setter,请将
您的方法的问题是,您不能向集合中添加任何项-我将具有类似list的私有结构,然后将这些项作为可枚举项公开:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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(); } } } |
如果您希望其他类创建角色列表(我不推荐),那么我不会亲自初始化可枚举的。
将私有列表公开为IEnumerable的典型问题是类的客户机可以通过强制转换来处理它。此代码可以工作:
1 2 3 |
通过实现迭代器,可以避免这种情况:
1 2 3 4 5 6 | public IEnumerable<Role> Roles { get { foreach (var role in mRoles) yield return role; } } |
更大的问题是将
以下内容看起来更好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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返回它,这取决于你想如何使用它。
而且可以枚举。这里的