为什么';return';和';收益率回报率;在本例中具有相同的行为

本文关键字:return 收益率 回报率 为什么 | 更新日期: 2023-09-27 18:25:30

我正在阅读这篇关于流利风格语法的文章,并尝试了这个例子。我注意到,当我将YoungDogs()HerdingDogs()方法体转换为LINQ表达式时,yield returnreturn替换,但该方法的行为保持不变。

为什么将方法更改为LINQ表达式会改变返回数据的行为?

这是文章中概述的原始示例:

    public static IEnumerable<Dog> YoungDogs(this IEnumerable<Dog> dogs)
    {
        foreach (Dog d in dogs)
            if (d.Age < 10)
                yield return d;
    }
    public static IEnumerable<Dog> HerdingDogs(this IEnumerable<Dog> dogs)
    {
        foreach (Dog d in dogs)
            if ((d.Breed == Breed.BorderCollie) ||
                (d.Breed == Breed.Collie) ||
                (d.Breed == Breed.Sheltie))
                yield return d;
    }

这是改变了方法的完整程序:

class Program
{
    static void Main(string[] args)
    {
        foreach (Dog d in AllMyDogs().YoungDogs().HerdingDogs())
        {
            Console.WriteLine(d.ToString());
            if (d.Breed == Breed.JackRussell)
                break;
        }
        Console.ReadLine();
    }
    private static IEnumerable<Dog> AllMyDogs()
    {
        yield return new Dog("Kirby", Breed.BorderCollie, 14);
        yield return new Dog("Jack", Breed.JackRussell, 15);
        yield return new Dog("Ruby", Breed.Mutt, 4);
        yield return new Dog("Lassie", Breed.Collie, 19);
        yield return new Dog("Shep", Breed.Collie, 2);
        yield return new Dog("Foofoo", Breed.Sheltie, 8);
        yield return new Dog("Pongo", Breed.Dalmatian, 4);
        yield return new Dog("Rooster", Breed.WestHighlandTerrier, 1);
    }
}
static class DogFilters
{
    public static IEnumerable<Dog> YoungDogs(this IEnumerable<Dog> dogs)
    {
        return dogs.Where(d => d.Age < 10);
    }
    public static IEnumerable<Dog> HerdingDogs(this IEnumerable<Dog> dogs)
    {
        return dogs.Where(d => (d.Breed == Breed.BorderCollie) ||
                               (d.Breed == Breed.Collie) ||
                               (d.Breed == Breed.Sheltie));
    }
}
public enum Breed
{
    BorderCollie,
    Collie,
    Sheltie,
    JackRussell,
    Mutt,
    Dalmatian,
    WestHighlandTerrier
}
public class Dog
{
    public string Name { get; set; }
    public Breed Breed { get; set; }
    public int Age { get; set; }
    public Dog(string name, Breed breed, int age)
    {
        Name = name;
        Breed = breed;
        Age = age;
    }
    public bool TryBark(out string barkSound)
    {
        bool success = false;
        barkSound = "";
        if (Age <= 10)
        {
            success = true;
            barkSound = "Woof";
        }
        return success;
    }
    public string Bark()
    {
        string barkSound;
        if (!TryBark(out barkSound))
            throw new Exception("This dog can't bark");
        return barkSound;
    }
    public override string ToString()
    {
        return string.Format("{0} <{1}>, age {2}", Name, Breed.ToString(), Age);
    }
}

为什么';return';和';收益率回报率;在本例中具有相同的行为

dogs.Where(d => d.Age < 10);声明了一个序列,当调用YoungDogs时将返回该序列。将返回的是序列的声明,而不是"通过过滤器"的狗。只有当您请求时,您才会从dogs集合中获得实际对象。

在后台,Where封装了对yield return的调用,通过该调用,dogs中传递谓词的项一个接一个地返回。发生这种情况的原因如下:

// That declares the sequence, you want to get. 
// In dogsWithAgeLessThanTen you don't have actaully any dog.
var dogsWithAgeLessThanTen = dogs.Where(d => d.Age < 10);
// Now you request the above query to be executed, that's called lazy loading. 
// Here you get one after the other the dogs that have age less than 10.
// The Enumerator you get from the dogsWithAgeLessThanTen returns your data 
// through a yield return statement.
foreach(var dog in dogsWithAgeLessThanTen)
{
}

以上内容相同,关于结果,将返回以下内容:

public static IEnumerable<Dog> YoungDogs(this IEnumerable<Dog> dogs)
{
    foreach (Dog d in dogs)
        if (d.Age < 10)
            yield return d;
}
var dogsWithAgeLessThanTen = dogs.YoungDogs();
foreach(var dog in dogsWithAgeLessThanTen)
{
}