为什么IEnumerable <T>成功枚举两次没有我做任何重置它?

KSw*_*t87 1 c# wpf ienumerable

当我对拉取请求进行更改时,我注意到了今天有趣的事情.以下是我的代码:

    public List<MatColor> Colors { get; set; }

    public List<Customer> Customers { get; set; }

    public ProductViewModel()
    {
        this.Colors = new List<MatColor>();
        this.Customers = new List<Customer>();

        var products = this.LoadProductViewList();

        this.LoadColorComboBox(products);
        this.LoadCustomerComboBox(products);
    }

    public void LoadColorComboBox(IEnumerable<Product> products)
    {
        this.Colors.Clear();

        this.Colors = products.Select(p => new MatColor()
        { Code = p.ColorCode, Description = p.ColorDescription })
                                            .DistinctBy(p => m.Code).DistinctBy(p => p.Description).ToList();
    }

    private void LoadCustomerComboBox(IEnumerable<Product> products)
    {
        this.Customers.Clear();

        this.Customers = products.Select(p => new Customer()
        { Name = p.CustomerName, Number = p.CustomerNumber })
                                              .DistinctBy(p => p.Number).DistinctBy(p => p.Name).ToList();
    }
Run Code Online (Sandbox Code Playgroud)

这段代码完成了我想要的一切.它成功地填充了ColorsCustomers列表.我理解为什么它总会成功填充Colors列表.那是因为LoadColorComboBox(...)首先被召唤.

IEnumerable<T>只能枚举,ONCE,对吗?因此,一旦它被枚举LoadColorComboBox(...),它如何成功重置并因此再次枚举LoadCustomerComboBox(...)?我已经检查了返回的底层类型LoadProductViewList()- 它调用一个返回一个的REST服务Task<IEnumerable<Product>>.我的IEnumerable<Product>某种方式是作为一个价值传递的吗?它不是原始的,所以我认为它是一个引用类型,因此,默认情况下将通过引用传入,这将导致第二种方法爆炸.有人可以告诉我我在这里没有看到什么吗?

Ser*_*rvy 7

并且IEnumerable是一个GetEnumerator方法的对象,它能够为您提供一个枚举器.通常人们会期望它能够为您提供任意数量的普查员.某些特定的实现可能不支持它,但接口的合同是它应该能够为您提供任意数量的实现.

至于IEnumerator它吐出的实例,它们技术上确实有一个Reset方法,应该将它设置回序列的"开始".但实际上,大多数实现都倾向于不支持"reset"操作符,只是在调用方法时抛出异常.

在你的情况下,你实际上IEnumerator并没有重置并尝试使用它来获取序列的值两次(这不起作用,因为你用来创建序列支持的LINQ方法中没有任何迭代器被重置).你正在做的只是获得多个不同的枚举器,这些LINQ方法都支持这些枚举器.