Why do "return" and "yield return" have the same behavior in this example?

I was reading this article about free text syntax and I tried this example. I noticed that when I converted the method bodies to YoungDogs()

and HerdingDogs()

into LINQ expressions, it yield return

was replaced by return

, but the behavior of the method remained the same.

Why does changing a method in a LINQ expression change the behavior of the returned data?

This is the original example described in the article:

    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;
    }

      

This is the complete program with modified methods:

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);
    }
}

      

+3


source to share


1 answer


This one dogs.Where(d => d.Age < 10);

declares a sequence that YoungDogs

will return when called . The thing that will be returned is the declaration of the sequence, not the dogs that "pass your filter". You will only get the actual objects from the collection dogs

when you ask for them.

Under the hood, a Where

call is encapsulated yield return

through which the elements in dogs

that pass the predicate are returned one by one. This comes from the affliction below:

// 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 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)
{

}

      



The above is the same, regarding the results, taht will be returned with the following:

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)
{

}

      

+3


source







All Articles