I have a class Person:
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) {}
}
And a class People which holds a collection of Person objects:
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);
}
}
Now I wanted to try making a LINQ join query, which tries to group persons with the same Name property, creating a new anonymous object which hold the name, and both the surnames (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 });
Now the problem is that if I execute this query I get a segmentation fault: GetEnumerator() gets called infinitely until the stack is full.
So I can imagine that Linq is calling GetEnumerator() many times
No, that's not the case. The problem is in your implementation of IEnumerable
, notably here:
public IEnumerator<Person> GetEnumerator()
{
return GetEnumerator();
}
That method is recursive. You're probably expecting it to call the explicit interface implementation, but it's not - it's just recursing.
Typically, you make the explicit interface implementation call the public method:
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();
}
Basically, you'd have seen the same effect if you'd just used a normal foreach
loop:
foreach (var person in people)
{
// You'd never get this far
}
It has nothing to do with LINQ.
See more on this question at Stackoverflow