【问题标题】:Yield return changes the order of chained call methodsyield return 改变了链式调用方法的顺序
【发布时间】:2016-05-13 23:08:58
【问题描述】:

我正在尝试使用 IEnumerator 来了解收益回报。在尝试了以下简单示例后,我发现链中的最后一个方法首先执行。这是我没想到的。

    public static void Example()
    {
        List<Pet> pets =
               new List<Pet>{ new Pet { Name="Barley", Age=8 },
                             new Pet { Name="Boots", Age=4 }
                             };

        var p1 = pets.ReturnPetAgeGreatThan2().ReturnPetAgeGreatThan4();

        foreach (var p in p1)
        {
            // Removed it to keep it simple  
            //Console.WriteLine("Pet Name:{0},Age:{1}", p.Name, p.Age);
        }

        Console.ReadLine();

    }

    public static IEnumerable<Pet> ReturnPetAgeGreatThan2(this IEnumerable<Pet> p)
    {
        Console.WriteLine("I am in ReturnPetAgeGreatThan2");

        foreach (var par in p)
        {
            if (par.Age > 2)
                yield return par;
        }
    }

    public static IEnumerable<Pet> ReturnPetAgeGreatThan4(this IEnumerable<Pet> p)
    {
        Console.WriteLine("I am in ReturnPetAgeGreatThan4");

        foreach (var par in p)
        {
            if (par.Age > 4)
                yield return par;
        }
    }
}

输出

    I am in ReturnPetAgeGreatThen4
    I am in ReturnPetAgeGreatThen2

但是一旦我删除了yield return,并将函数更改为只使用return。方法是按顺序调用的。

    public static IEnumerable<Pet> ReturnPetAgeGreatThan2(this IEnumerable<Pet> p)
    {
        Console.WriteLine("I am in ReturnPetAgeGreatThen2");
        var result = p.Where(x => x.Age > 2);

        return result;
   }

    public static IEnumerable<Pet> ReturnPetAgeGreatThan4(this IEnumerable<Pet> p)
    {
        Console.WriteLine("I am in ReturnPetAgeGreatThen4");
        var result = p.Where(x => x.Age > 4);
        return result;
     }

输出

     I am in ReturnPetAgeGreatThen2
     I am in ReturnPetAgeGreatThen4

任何帮助理解这一点将不胜感激。

【问题讨论】:

    标签: c# yield-return


    【解决方案1】:

    使用yield return,您正在创建一个隐式枚举。在这种情况下,编译器实际上做了很多代码转换。这里的要点是,每当返回值时,都会保存方法的 state。

    所以这里发生的情况基本上是你的第一个方法在调用时返回一个IEnumerable立即,但是为它生成值的代码还不会运行。仅在枚举时才会发生这种情况。该枚举发生在您的第二种方法中,该方法使用foreach。因此,您首先会看到第二种方法的输出,因为第一种方法的输出仅在生成可枚举的第一个值时发生。

    在您的第二种情况下,您实际上并没有枚举任何内容,而是返回 IEnumerables,它只会在枚举时生成/过滤值。但是,由于您的方法主体不再包含 yield return,因此编译器将不再将其重写为实际上成为一个生成值的 IEnumerable,因此它只是一个普通方法并立即运行并在您期望的顺序。

    【讨论】:

      猜你喜欢
      • 2011-02-08
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 2014-09-26
      • 1970-01-01
      • 2017-01-02
      • 1970-01-01
      • 2015-05-23
      相关资源
      最近更新 更多