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.
我正在尝试找到一种从通用基础 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.