2014-10-03 56 views
3

我正在讀這個article about fluent-style syntax,我試過這個例子。我注意到,當我將YoungDogs()HerdingDogs()方法體轉換爲LINQ表達式時,yield return被替換爲return,但該方法的行爲保持不變。爲什麼在本例中'return'和'yield return'具有相同的行爲?

爲什麼將方法更改爲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); 
    } 
} 
+4

的'Where'方法封裝了'yield'。 – jmcilhinney 2014-10-03 11:38:09

+0

查看Jon Skeet的edulinq系列。他很好地解釋了Linq如何實施的細節。以下是「Where」部分的鏈接http://edulinq.googlecode.com/hg/posts/02-Where.html。 – juharr 2014-10-03 11:46:57

+0

@jmcilhinney不是。你可以使用'Where'並仍然使用'yield return',你可以*不使用'Where'並仍然使用'return'。 – Rawling 2014-10-03 12:23:24

回答

3

dogs.Where(d => d.Age < 10);聲明瞭一個序列,其當YoungDogs將被叫會被退回。將返回的是聲明序列,而不是「通過您的過濾器」的狗。只有在您請求時纔會收到dogs集合中的實際對象。

在引擎蓋下Where封裝了對yield return的調用,通過該調用,dogs中傳遞謂詞的項將一個接一個地返回。出現這種情況下面inastance:

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

} 

以上是相同的,對於taht將與下面的一個被返回的結果:

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

} 
相關問題