C#通过<t>定义基类

时间:2015-05-04 19:06:43

标签: c# generics inheritance dynamic

我试图找到一种从泛型基类派生类的方法。说:

sealed public class Final : Base<Something>
{

}

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

}

在C#中,这似乎不可能。

是否还有其他解决方案可以实现类似的目标?

我发现了这个StackOverflow question,但它似乎没有解决问题,或者至少我不明白它应该如何。

修改

我想得到的结果是能够做到这样的事情:

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

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

4 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:1)

这是你想要的吗?

sealed public class Final : Base<int>{

}

public class Base<T> {

}

答案 2 :(得分:0)

如果Final也是一个通用类,你只能这样做,如下所示:

public sealed class Final<T> : Base<T>

然后,您可以将T上的类型限制设为class,仅允许引用类型为T,或仅允许Base<T>的实例源自Base<T>的类型:

public class Base<T> where T : Base<T>

答案 3 :(得分:0)

我不知道这个问题的上下文,但是在一个项目中遇到了同样的问题,在这个项目中我不得不扩展已经由许多其他人派生的基类。喜欢:

abstract class Base {}
class FinalA : Base {}
class FinalB : Base {}

// Now create extended base class and expect final classes to be extended as well:
class BetterBase : Base {}

解决方案是创建公共祖先并通过属性进行连接:

abstract class Foundation {}
abstract class Base : Foundation 
{
    Foundation Final { get; }
}
class FinalA : Foundation {}
class FinalB : Foundation {}
class FinalC : Foundation
{
    Foundation Base { get; }
}

// Here's the desired extension:
class BetterBase : Base {}

现在BetterBase可以与最终类建立连接,并且如果需要,最终类也可以与(Better)Base建立连接,如FinalC类所示。