C# 从通用基础派生 Class (T : U<T>)

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

我正在尝试找到一种从通用基础 class 派生 class 的方法。说:

sealed public class Final : Base<Something>
{

}

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

}

在 C# 中这似乎是不可能的。

是否有任何其他解决方案可以实现类似的效果?

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

编辑:

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

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

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

这是你想要的吗?

sealed public class Final : Base<int>{

}

public class Base<T> {

}

只有当 Final 也是通用的 class 时,您才能这样做,例如:

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

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

的类型
public class Base<T> where T : Base<T>

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
 }

您的 foreach 循环表明:class Anything : Final { … }.

这显然会按照您的计划和命名方式扭转继承层次结构。 (继承关系中不能有循环)。


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

让我详细说明一下这部分。我会将您的示例进一步缩减为 class Base<T> : T.

这是不可能的,这是有充分理由的。想象一下:

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() { … }
}

如果 class Base<T> : T 被允许,你会遇到各种荒谬的情况。

  • Base<A> 是荒谬的,因为 Frobble 不能在派生的 class 中被覆盖。
  • Base<B> 是荒谬的,因为你不能覆盖一个方法 基地 class 中不存在。
  • Base<C> 不起作用,因为没有 Fiddle 方法可以调用。
  • Base<D> 将不起作用,因为您不能调用抽象方法。
  • 只有 Base<E> 有效。

编译器如何知道如何正确编译 Base<T> 并分析依赖于它的代码?

重点是您不能从编译时未知的 class 派生。 T是一个参数,即一个变量,一个占位符。所以 class Base<T> : T 基本上就像在说,"Base<T> 继承自某些(未知)class"。 Class 继承是一种类型关系,需要在编译时知道所涉及的两种类型。 (实际上,这不是一个超级精确的声明,因为您可以从泛型继承,例如 class SpecialList<T> : List<T>。但至少,派生的 class 必须知道哪些成员(方法、属性等) .) 在基础 class.)

中可用

我不知道这个问题的上下文,但我 运行 遇到了一个项目的同一个问题,我必须使扩展基础 class 已经由很多其他的。喜欢:

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 与 final class 有联系,如果需要,final classes 也可以与 (Better)Base 联系,如 FinalC class.