Calling Enumerable.Join on a IEnumerable collection causes segmentation fault

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.

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow