【问题标题】:How IEnumerable are stored in memory in c#?IEnumerable 如何在 C# 中存储在内存中?
【发布时间】:2014-09-11 06:41:48
【问题描述】:

Like Array 是顺序内存分配,list 可能会以与链表相同的方式存储在内存中(如果我错了,请纠正我)。 IEnumerable 如何在 C# 中存储在内存中? 假设我有一堂课

 public class Employee
 {
      public int Id { get; set; }
      public string Name { get; set; }
 }

在以下两种情况下,内存分配将有何不同。为什么编译器不允许我们编辑 IEnumerables

IList<Employee> EmpList ;

Or

IEnumerables<Employee> EmpList ;

【问题讨论】:

  • IEnumerable 是一个interface。这在很大程度上取决于具体的实施。 ArrayLinkedList 也是 IEnumerable 但您指出的内存存储是不同的。
  • 它可以是,也可以是其他的,这取决于。界面不暗示什么。
  • 不可能使用IEnumerable&lt;T&gt;来存储集合,因为接口IEnumerable&lt;T&gt;不允许插入元素;它只允许阅读。
  • @Codor 不。 List&lt;T&gt; 实现 IEnumerable&lt;T&gt; 但列表绝对是集合。我会说 IEnumerable 不公开插入接口,但它可以(但不必,例如机器状态)包含集合。
  • @shiv - 同样,IList&lt;T&gt;IEnumerable&lt;T&gt; 只是接口。这取决于项目如何存储的实际实现。例如List&lt;T&gt;(两者都实现)恰好将项目存储在底层数组中。但这只是一个实现细节,将来可能会改变。 - 此外,对于所有引用类型,只有引用“存储”在该底层数组中。实际的对象数据可能在任何地方,随机分布。

标签: c# .net memory-management


【解决方案1】:

这个问题无法回答。

这取决于实现IEnumerable的底层对象。

它可能是一个数组,在这种情况下,内存表示就是一个数组,或者它可能是一个延迟实现的枚举器,根据需要生成值,在这种情况下,它实际上并没有其他内存表示而不是该方法中状态机的局部变量。

【讨论】:

    【解决方案2】:

    一个 IEnumerable 变量存储一个对象引用(作为实现细节,它将是四个或八个字节,具体取决于进程)。 System.Collections.Generic.List 变量、数组变量、ICollection 变量或(尽管与问题无关)任何引用类型变量也是如此。

    对象的枚举器生成的数据将被存储,但由引用指向的对象决定。在某些情况下,它将仅存储第一个元素以及枚举器用来计算后续元素的一些信息(例如 System.Linq.Enumerable.Range)。在其他情况下,对象可以是数组或 S.C.G.List(顺序存储——列表使用数组进行存储)、链表、散列集或排序集(分别使用散列表和二叉树) ,或者任何其他人想要梦想和实现的东西。

    在您关于内存分配的问题中,两者之间的内存使用没有区别

    IList<Employee> empList = new List<Employee>();
    

    IEnumerable<Employee> empList = new List<Employee>();
    

    这两者之间的区别在于您可以从 empList 对象引用中调用对象的方法。在第一种情况下,您仅限于 IList 中定义的许多成员及其继承的接口,因此您可以改变集合。第二种情况,只能调用GetEnumerator,所以不能对集合进行变异。

    【讨论】:

      【解决方案3】:

      IEnumerable只是一个接口,它应该做的就是

      http://msdn.microsoft.com/en-us/library/cc317868.aspx

      提供一个枚举器:

       public IEnumerator GetEnumerator() 
      

      枚举器的实现可能不同, 事实上,它可能根本没有数据存储

        // Generates 0, 1, 2, ... sequence
        public sealed class Sample: IEnumerable {
          public IEnumerator GetEnumerator() {
            for(int i = 0;; ++i)
              yield return i;
          }  
        }
      

      【讨论】:

      • 从技术上讲,这是在编译器生成的枚举器实例上至少存储一个i,以及.Current 值... ;p
      猜你喜欢
      • 2022-01-16
      • 2012-06-28
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 2013-01-14
      • 1970-01-01
      相关资源
      最近更新 更多