我不认为我想要的是可能的,但我希望有人可以验证这一点,也许可以解释为什么不可能。
我们有Bar<T>
的继承,我们无法触及Bar<T>
abstract class Foo<T> : Bar<T>
我们提供Foo<T>
由第三方实施,我们还想要规定从Foo<T>
继承的任何类都是T
的指定类型。
这当然可以由第三方手动完成,例如
class Fizz : Foo<Fizz>
然而,我发现重复Fizz
繁琐而丑陋。
是否可以让Foo<T>
自动使用Fizz
作为T
的指定类型?
换句话说,是否可以让Foo<T>
在这些方面实施某些内容
abstract class Foo : Bar<T>
where T : "Whatever class inherits from Foo"
...我不相信是可能的,因为我找不到合适的泛型类型约束。 是否可以做这样的事情
[SomeBlackMagic("Dear compiler, T is whatever inherits from Foo.")]
abstract class Foo : Bar<T>
...这样Fizz
的实现可能只是
class Fizz : Foo
答案 0 :(得分:2)
这可能不是您想要的,但是您是否考虑过在Foo<T>
上实施界面,以便始终确定通用T
的类型是什么?
public class Bar<T>
{}
public interface IDev
{}
public abstract class Foo<T> : Bar<T> where T : IDev
{}
public class Fizz : Foo<Fizz>, IDev
{}
它可以让你控制传入的通用对象。
答案 1 :(得分:2)
这就是所谓的Curiously Recurring Template Pattern。不幸的是,大多数强类型语言都无法消除这种代码味道。 C#没有办法改进这一点。
您可以使用运行时检查,但代价是编译时检查。此外,您实际上不会在类接口中使用该类型。例如,您将无法执行abstract class Foo<T> { public T Bar() { ... } }
之类的操作,因为编译器不会知道T
。
答案 2 :(得分:2)
我们还想要规定从Foo继承的任何类都是T的指定类型。
此要求可以作为自定义Roslyn分析器实现。
虽然遗憾的是这篇文章abstract class Foo : Bar<T>
不可能,但T
通用参数应该按某种类型关闭,或者Foo
也必须是通用的。
答案 3 :(得分:0)
abstract class Foo<T> : Bar<T>
where T : Foo<T>
{ /* ... */ }
class Fizz : Foo<Fizz>
{ /* ... */ }
我知道这不是你想要的,但它是最好的选择。