Is it better to use Enumerable.Empty() as opposed to new List() to initialize an IEnumerable?

前端 未结 6 831
伪装坚强ぢ
伪装坚强ぢ 2020-12-23 02:22

Suppose you have a class Person :

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


        
相关标签:
6条回答
  • 2020-12-23 02:58

    I think most postings missed the main point. Even if you use empty array or empty list, those are objects and they are stored in memory. Than Garbage Collector has to take care of them. If you are dealing with high throughput application, it could be noticeable impact.

    Enumerable.Empty does not create an object per call thus putting less load on GC.

    If the code is in low-throughput location, then it boils down to aesthetic considerations though.

    0 讨论(0)
  • 2020-12-23 03:01

    The typical problem with exposing the private List as an IEnumerable is that the client of your class can mess with it by casting. This code would work:

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

    You can avoid this by implementing an iterator:

    public IEnumerable<Role> Roles {
      get {
        foreach (var role in mRoles)
          yield return role;
      }
    }
    
    0 讨论(0)
  • 2020-12-23 03:16

    Assuming you actually want to populate the Roles property somehow, then encapsulate that by making it's setter private and initialising it to a new list in the constructor:

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

    If you really really want to have the public setter, leave Roles with a value of null and avoid the object allocation.

    0 讨论(0)
  • 2020-12-23 03:16

    The problem with your approach is that you can't add any items to the collection - I would have a private structure like list and then expose the items as an 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(); }
        }
    }
    

    If you intend some other class to create the list of roles (which I wouldn't recommend) then I wouldn't initialise the enumerable at all in Person.

    0 讨论(0)
  • 2020-12-23 03:24

    I think Enumerable.Empty<T> is better because it is more explicit: your code clearly indicates your intentions. It might also be a bit more efficient, but that's only a secondary advantage.

    0 讨论(0)
  • 2020-12-23 03:25

    On the performance front, let's see how Enumerable.Empty<T> is implemented.

    It returns EmptyEnumerable<T>.Instance, which is defined as:

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

    Static fields on generic types are allocated per generic type parameter. This means that the runtime can lazily create these empty arrays only for the types user code needs, and reuse the instances as many times as needed without adding any pressure on the garbage collector.

    To wit:

    Debug.Assert(ReferenceEquals(Enumerable.Empty<int>(), Enumerable.Empty<int>()));
    
    0 讨论(0)
提交回复
热议问题