C# 为什么IEnumerable成功地枚举了两次,而我没有对其进行任何重置?

C# 为什么IEnumerable成功地枚举了两次,而我没有对其进行任何重置?,c#,wpf,ienumerable,C#,Wpf,Ienumerable,今天我在修改拉请求时注意到了一些有趣的事情。下面是我的代码: public List<MatColor> Colors { get; set; } public List<Customer> Customers { get; set; } public ProductViewModel() { this.Colors = new List<MatColor>(); this.Customers

今天我在修改拉请求时注意到了一些有趣的事情。下面是我的代码:

    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();
    }
这段代码做了我想做的一切。它成功地填充了颜色和客户列表。我理解为什么它总是能成功地填充颜色列表。那是因为LoadColorComboBox。。。先接到电话

但是一个IEnumerable只能被枚举一次,对吗?那么,一旦它在LoadColorComboBox中被枚举,它是如何成功重置并在LoadCustomerComboBox中再次枚举的呢。。。?我已经检查了LoadProductViewList返回的底层类型——它调用一个REST服务,返回一个任务。我的IEnumerable是否以某种方式作为值传递?它不是一个原语,所以我觉得它是一个引用类型,因此,它将作为默认值通过引用传入,这将导致第二个方法崩溃。有人能告诉我我没看到什么吗

但是一个IEnumerable只能被枚举一次,对吗

不可以。IEnumerable可以枚举任意次数。但对于每个枚举,每个项只能生成一次

在您的情况下,对于每个需要产品列表的LINQ查询,产品将被枚举一次。。。所以一次在LoadColorComboBox中,一次在LoadCustomerComboBox中

但是一个IEnumerable只能被枚举一次,对吗

不可以。IEnumerable可以枚举任意次数。但对于每个枚举,每个项只能生成一次

在您的情况下,对于每个需要产品列表的LINQ查询,产品将被枚举一次。。。因此,一次在LoadColorComboBox中,一次在LoadCustomerComboBox中。

和IEnumerable是一个带有GetEnumerator方法的对象,它可以为您获取一个枚举器。一般来说,人们希望它能给你提供任意数量的枚举数。一些特定的实现可能不支持它,但接口的契约是它应该能够提供您想要的数量

至于它吐出的IEnumerator实例,从技术上讲,它们确实有一个重置方法,应该将其设置回序列的开始。然而,在实践中,大多数实现往往不支持reset操作符,只在调用该方法时引发异常

在您的例子中,实际上并没有重置IEnumerator并尝试使用它两次获取序列值,这是行不通的,因为用于创建序列的LINQ方法中没有一个迭代器支持重置。您所做的只是获取多个不同的枚举数,这些LINQ方法都支持这些枚举数。

而IEnumerable是一个带有GetEnumerator方法的对象,它可以为您获取一个枚举数。一般来说,人们希望它能给你提供任意数量的枚举数。一些特定的实现可能不支持它,但接口的契约是它应该能够提供您想要的数量

至于它吐出的IEnumerator实例,从技术上讲,它们确实有一个重置方法,应该将其设置回序列的开始。然而,在实践中,大多数实现往往不支持reset操作符,只在调用该方法时引发异常


在您的例子中,实际上并没有重置IEnumerator并尝试使用它两次获取序列值,这是行不通的,因为用于创建序列的LINQ方法中没有一个迭代器支持重置。您所做的只是获取多个不同的枚举数,这些LINQ方法都支持这些枚举数。

IEnumerable可以根据需要进行多次枚举。我不知道你是从哪里得到这个想法的。为什么一个IEnumerable只能被枚举一次呢。它只是可枚举集合最简化的接口之一。列表还实现IEnumerable,还可以无限次枚举。您可能会混淆枚举和延迟执行。这通常只发生一次。@BjörnBoxstart延迟执行只发生一次的语句是什么意思?延迟执行只是意味着直到需要时才执行计算;如果您多次迭代延迟执行的序列,它将多次执行这些计算。@BJ Myers-我正在研究答案,因为我不了解IEnumerable与其他类型的集合(如IList)相比的所有更精细的工作原理。不管怎么说,尽管我很后悔问这个问题,但我不知道我是从哪里得到这样的想法:一个IEnumerable只能被枚举一次,而没有某种类型的位置重置,但是这里有一个想法,我从哪里得到了一个IEnumerable,你只能列举一次,这样人们就能理解我的思想起源:IEnumerable可以被列举任意多次
. 我不知道你是从哪里得到这个想法的。为什么一个IEnumerable只能被枚举一次呢。它只是可枚举集合最简化的接口之一。列表还实现IEnumerable,还可以无限次枚举。您可能会混淆枚举和延迟执行。这通常只发生一次。@BjörnBoxstart延迟执行只发生一次的语句是什么意思?延迟执行只是意味着直到需要时才执行计算;如果您多次迭代延迟执行的序列,它将多次执行这些计算。@BJ Myers-我正在研究答案,因为我不了解IEnumerable与其他类型的集合(如IList)相比的所有更精细的工作原理。不管怎么说,尽管我很后悔问这个问题,但我不知道我是从哪里得到这样的想法:一个IEnumerable只能被枚举一次,而没有某种类型的位置重置,但是这里有一个想法,我从哪里得到了一个IEnumerable,你只能列举一次IEnumerable,这样人们就能理解我的想法的起源:你可以创建一个IEnumerator,它可以多次生成一个项。这就像新的一样简单{嗨,嗨}。重复该操作,您将获得两次相同的值。两个具有相同值的项=/=相同项两次。虽然hi作为字符串常量将被插入,但有两个不同的内存位置指向同一个字符串,并且枚举器将精确返回每个位置一次。IEnumerator没有项的概念。它有它产生的价值。就这样。它可以产生不同的、唯一的或任何它想要的值。你可以写一个枚举数来产生任何结果。当然可以。这是你的密码。您还可以编写一个使O/S崩溃的实现。但是,我建议,使O/S崩溃或两次生成同一项的IEnumerable实现都有实现缺陷。谢天谢地,您的示例使用的CLR类型没有任何问题,因此我支持我的答案。同样,在处理IEnumerator时,项的概念并不存在。这句话本身毫无意义。当然,如果您有一个IEnumerator,它被设计用于迭代具有某些项概念的集合,那么这种迭代器很可能被设计为只生成集合中的每个项一次,但是有很多枚举器与集合无关,因此没有项的概念。You's语句只适用于实际枚举数的一小部分,但您错误地将其表示为所有枚举数的通用性。您可以创建多次生成项的IEnumerator。这就像新的一样简单{嗨,嗨}。重复该操作,您将获得两次相同的值。两个具有相同值的项=/=相同项两次。虽然hi作为字符串常量将被插入,但有两个不同的内存位置指向同一个字符串,并且枚举器将精确返回每个位置一次。IEnumerator没有项的概念。它有它产生的价值。就这样。它可以产生不同的、唯一的或任何它想要的值。你可以写一个枚举数来产生任何结果。当然可以。这是你的密码。您还可以编写一个使O/S崩溃的实现。但是,我建议,使O/S崩溃或两次生成同一项的IEnumerable实现都有实现缺陷。谢天谢地,您的示例使用的CLR类型没有任何问题,因此我支持我的答案。同样,在处理IEnumerator时,项的概念并不存在。这句话本身毫无意义。当然,如果您有一个IEnumerator,它被设计用于迭代具有某些项概念的集合,那么这种迭代器很可能被设计为只生成集合中的每个项一次,但是有很多枚举器与集合无关,因此没有项的概念。You's语句只适用于实际枚举数的一小部分,但您错误地将其作为所有枚举数的通用性来表述。感谢您为我详细解释……特别是指出重置方法。我发誓,在QuickWatch期间,我收到了不少错误,其中消息指出枚举数或可能是枚举数?已被枚举-因此,我得到的印象是IEnumerable只能被枚举一次。感谢您为我详细说明这一点…特别是指出重置方法。我发誓,在QuickWatch期间,我收到了不少错误,其中消息指出枚举数或可能是枚举数?已经被列举了——因此我得到的印象是一个IEnumerable只能列举一次。