How does recursive inheritance work ? class PersonInfoBuilder<SELF> : PersonBuilder where SELF : PersonInfoBuilder<SELF>

Viewed 80

This seems like a chicken and an egg problem to me.

class PersonInfoBuilder<SELF> : PersonBuilder 
where SELF : PersonInfoBuilder<SELF>

// PersonBuilder is an abstract class in this example. How does PersonInfoBuilder<SELF> : PersonBuilder which has the constrains of SELF : PersonInfoBuiler<SELF>

1 Answers

The inheritance to PersonBuilder is just noise, your question is about this pattern:

class PersonInfoBuilder<SELF> where SELF : PersonInfoBuilder<SELF>

Let's change the names and make a convoluted example that makes use of the pattern:

abstract class CompatibleAnimal<T>  where T: CompatibleAnimal<T>
{
    public abstract CompatibleAnimal<T> BreedWith(T t);
}

abstract class Equine: CompatibleAnimal<Equine> 
{
    public override abstract CompatibleAnimal<Equine> BreedWith(Equine t);
}

class Mule: Equine {
    public override CompatibleAnimal<Equine> BreedWith(Equine t)
    {
        return null;
    }

    public override string ToString() => "mules";
}

class Horse: Equine {
    public override CompatibleAnimal<Equine> BreedWith(Equine t)
    {
        if (t is Donkey)
            return new Mule();
        if (t is Horse)
            return new Horse();
        return null;
    }

    public override string ToString() => "horses";
}

class Donkey: Equine
{
    public override CompatibleAnimal<Equine> BreedWith(Equine t)
    {
        if (t is Donkey)
            return new Donkey();
        if (t is Horse)
            return new Mule();
        return null;
    }

    public override string ToString() => "donkeys";
}

And now:

public static void Main() {
    Console.WriteLine(
        $@"If you cross horses with horses you get {
            new Horse().BreedWith(new Horse())?.ToString() ?? "nothing"}");
     Console.WriteLine(
        $@"If you cross donkeys with donkeys you get {
            new Donkey().BreedWith(new Donkey())?.ToString() ?? "nothing"}");
      Console.WriteLine(
        $@"If you cross horses with donkeys you get {
            new Horse().BreedWith(new Donkey())?.ToString() ?? "nothing"}");
     Console.WriteLine(
        $@"If you cross mules with mules you get {
            new Mule().BreedWith(new Mule())?.ToString() ?? "nothing"}");
     Console.WriteLine(
        $@"If you cross mules with donkeys you get {
            new Mule().BreedWith(new Donkey())?.ToString() ?? "nothing"}");
              Console.WriteLine(
        $@"If you cross mules with horses you get {
            new Mule().BreedWith(new Horse())?.ToString() ?? "nothing"}");
}

And of course, if you create a similar class hierarchy for canines, the type system won't allow you to accidentally breed an equine with a canine, which seems like a good idea.

Related