Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
}
like image 277
Noel Widmer Avatar asked May 04 '15 19:05

Noel Widmer


1 Answers

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.)

like image 152
stakx - no longer contributing Avatar answered Sep 24 '22 11:09

stakx - no longer contributing