我正在读这个article about fluent-style syntax,我尝试了这个例子。我注意到,当我将YoungDogs()
和HerdingDogs()
方法体转换为LINQ表达式时,yield return
被替换为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);
}
}
答案 0 :(得分:3)
这个dogs.Where(d => d.Age < 10);
声明一个序列,当将调用YoungDogs
时将返回该序列。将返回的是序列的声明,而不是&#34; 通过过滤器的狗&#34;。只有在您请求时,您才能从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)
{
}
以上是相同的,关于结果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)
{
}