Sté*_*ane 133 c# linq constructor
假设你有一个人类:
public class Person
{
public string Name { get; set;}
public IEnumerable<Role> Roles {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
我显然应该在构造函数中实例化角色.现在,我曾经使用像这样的List:
public Person()
{
Roles = new List<Role>();
}
Run Code Online (Sandbox Code Playgroud)
但我在System.Linq命名空间中发现了这种静态方法
IEnumerable<T> Enumerable.Empty<T>();
Run Code Online (Sandbox Code Playgroud)
来自MSDN:
该
Empty(TResult)()方法缓存一个空的序列TResult.当它返回的对象被枚举时,它不会产生任何元素.在某些情况下,此方法对于将空序列传递给用户定义的方法非常有用
IEnumerable(T).它还可以用于为诸如的方法生成中性元素Union.有关此用法的示例,请参阅示例部分
那么编写这样的构造函数会更好吗?你用它吗?为什么?如果没有,为什么不呢?
public Person()
{
Roles = Enumerable.Empty<Role>();
}
Run Code Online (Sandbox Code Playgroud)
Vad*_*kan 154
我认为大多数帖子都错过了重点.即使您使用空数组或空列表,这些也是对象,它们存储在内存中.比垃圾收集者必须照顾他们.如果您正在处理高吞吐量应用程序,它可能会产生明显的影响.
Enumerable.Empty 不会为每个调用创建一个对象,从而减少了GC的负担.
如果代码处于低吞吐量位置,那么它可归结为美学考虑因素.
Tom*_*ier 86
我认为Enumerable.Empty<T>更好,因为它更明确:你的代码清楚地表明了你的意图.它也可能更高效,但这只是次要优势.
Dre*_*kes 21
在性能方面,让我们看看如何Enumerable.Empty<T>实现.
它返回EmptyEnumerable<T>.Instance,定义为:
internal class EmptyEnumerable<T>
{
public static readonly T[] Instance = new T[0];
}
Run Code Online (Sandbox Code Playgroud)
泛型类型的静态字段按泛型类型参数分配.这意味着运行时只能为用户代码需要的类型延迟创建这些空数组,并根据需要重复使用实例,而不会对垃圾收集器施加任何压力.
以机智:
Debug.Assert(ReferenceEquals(Enumerable.Empty<int>(), Enumerable.Empty<int>()));
Run Code Online (Sandbox Code Playgroud)
Nei*_*ell 12
假设你实际上想要以Roles某种方式填充属性,然后通过使它的setter私有并将其初始化为构造函数中的新列表来封装它:
public class Person
{
public string Name { get; set; }
public IList<Role> Roles { get; private set; }
public Person()
{
Roles = new List<Role>();
}
}
Run Code Online (Sandbox Code Playgroud)
如果你真的想拥有公共setter,请保留Roles值null并避免对象分配.
您的方法的问题是您不能将任何项添加到集合 - 我将有一个像列表的私有结构,然后将项目公开为Enumerable:
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(); }
}
}
Run Code Online (Sandbox Code Playgroud)
如果你打算让其他一些类创建角色列表(我不推荐),那么我就不会在Person中初始化所有可枚举的类.
将私有List暴露为IEnumerable的典型问题是,您的类的客户端可以通过强制转换来解决它.这段代码可行:
var p = new Person();
List<Role> roles = p.Roles as List<Role>;
roles.Add(Role.Admin);
Run Code Online (Sandbox Code Playgroud)
您可以通过实现迭代器来避免这种情况:
public IEnumerable<Role> Roles {
get {
foreach (var role in mRoles)
yield return role;
}
}
Run Code Online (Sandbox Code Playgroud)
这里更大的问题是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>();
}
}
}
Run Code Online (Sandbox Code Playgroud)
也许您应该看一下将其作为ReadonlyCollection返回的情况,具体取决于您要如何使用它。
而且Enumerable.Empty不在better这里,当Role通常为空时,效率要高一点。