我有一个人类:
public class Person
{
public string Name {get; set;}
public string Surname {get; set;}
public uint Age {get; set;}
public Person(string name, string surname, uint age)
{
Name= name;
Surname= surname;
Age= age;
}
public Person() : this("default","default",25) {}
}
包含Person对象集合的类People:
public class People : IEnumerable<Person>
{
private List<Person> people= new List<Person> ();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
people.GetEnumerator();
}
public IEnumerator<Person> GetEnumerator()
{
return GetEnumerator();
}
public void Add(Person p)
{
people.Add(p);
}
}
现在我想尝试创建一个LINQ连接查询,它尝试对具有相同Name属性的人进行分组,创建一个包含该名称的新匿名对象,以及两个姓氏(Surname1,Surname2):
People ppl1 = new People() {
new Person(),
new Person("Mario","",35),
new Person("Garcya","Luis",32)
};
People ppl2 = new People() {
new Person(),
new Person("Pablo","Escobar",82),
new Person("Claudio","Sevilla",33),
new Person("Garcya","",31)
};
var commonPpl=ppl1.Join<Person, Person, string, object>(ppl2, p => p.Name, p => p.Name,
(p1, p2) => new { Name = p1.Name, Surname1 = p1.Surname, Surname2 = p2.Surname });
现在的问题是,如果我执行此查询,我会遇到一个分段错误:GetEnumerator()被无限调用,直到堆栈已满。
答案 0 :(得分:7)
所以我可以想象Linq多次调用GetEnumerator()
不,事实并非如此。问题在于IEnumerable
的实施,特别是在这里:
public IEnumerator<Person> GetEnumerator()
{
return GetEnumerator();
}
该方法是递归的。你可能期待它来调用显式接口实现,但它不是 - 它只是递归。
通常,您使显式接口实现调用公共方法:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
// Call the public method. The body of this method wasn't even valid before,
// as it was calling `people.GetEnumerator() but not returning anything.
return GetEnumerator();
}
public IEnumerator<Person> GetEnumerator()
{
return people.GetEnumerator();
}
基本上,如果您使用普通foreach
循环,您已经看到了同样的效果:
foreach (var person in people)
{
// You'd never get this far
}
它与LINQ无关。