C# Derive From Generic Base Class (T : U<T>)

18,126

Solution 1

The result I'd like to get is to be able to do something like that:

 Anything[] anything;
 //Assign some Instances to anything 

 foreach(Final final in anything){
     //do something with final
 }

Your foreach loop suggests this: class Anything : Final { … }.

This obviously turns around the inheritance hierarchy as you planned and named it. (You cannot have cycles in your inheritance relationships).


public class Base<T> : T where T : Anything { …

Let me elaborate on this part for a bit. I'll reduce your example even further to just class Base<T> : T.

This is not possible, for good reason. Imagine this:

class Base<T> : T
{
    public override string Frobble()
    {
        Fiddle();
        return "*" + base.Frobble() + "*";
    }
}

class A
{
    public sealed string Frobble() { … }
}

class B
{
}

class C
{
    public virtual string Frobble() { … }
}

abstract class D
{
    public abstract void Fiddle();
    public virtual string Frobble() { … }
}

class E
{
    public void Fiddle() { … }
    public virtual string Frobble() { … }
}

You get all kinds of absurd situations if class Base<T> : T were allowed.

  • Base<A> would be absurd because Frobble cannot be overridden in a derived class.
  • Base<B> would be absurd because you cannot override a method that doesn't exist in the base class.
  • Base<C> doesn't work because there is no Fiddle method to call.
  • Base<D> would not work because you cannot call an abstract method.
  • Only Base<E> would work.

How would the compiler ever know how to correctly compile Base<T> and analyse code that depends on it?

The point is that you cannot derive from a class that is not known at compile-time. T is a parameter, i.e. a variable, a placeholder. So class Base<T> : T is basically like saying, "Base<T> inherits from some (unknown) class". Class inheritance is a type relationship that requires both involved types to be known at compile-time. (Actually, that's not a super-precise statement because you can inherit from a generic type such as class SpecialList<T> : List<T>. But at the very least, the derived class has to know what members (methods, properties, etc.) are available in the base class.)

Solution 2

Is this what you want?

sealed public class Final : Base<int>{

}

public class Base<T> {

}
Share:
18,126
Noel Widmer
Author by

Noel Widmer

Noël is a Senior Software Engineer at Digitec Galaxus AG.In his spare time he currently develops a 3D puzzle game.

Updated on June 15, 2022

Comments

  • Noel Widmer
    Noel Widmer almost 2 years

    I am trying to find a way to derive a class from a generic base class. Say:

    sealed public class Final : Base<Something>
    {
    
    }
    
    public class Base<T> : T
        where T : Anything // <-- Generics do not allow this
    {
    
    }
    

    In C# this does not seem to be possible.

    Is there any other solution to achieve something similar to this?

    I found this StackOverflow question, but it doesn't seem to solve the issue, or at least I do not understand how it should.

    EDIT:

    The result I'd like to get is to be able to do something like that:

    Anything[] anything;
    //Assign some Instances to anything 
    
    foreach(Final final in anything){
         //do something with final
    }
    
  • Noel Widmer
    Noel Widmer almost 9 years
    Base<T> should now derive from <T>, which is int in this case
  • vendettamit
    vendettamit almost 9 years
    @NoelWidmer That is called generic constraints where you place condition to restrict the type T.