能否让继承Foo的类自动作为泛型参数T,避免重复声明?
答案:C# 原生不支持这种自动绑定泛型参数的特性
很遗憾,你想要的让Foo自动把继承它的子类作为Bar<T>的泛型参数T的功能,在C#里是没有原生支持的,原因主要有这几点:
- 泛型约束做不到自动推断:你能给
Foo<T>加的最强约束是where T : Foo<T>,这能强制第三方传入的T必须是Foo的子类,但没法让编译器自动把T填充成当前定义的子类(比如Fizz)——编译器没有逻辑能关联“正在定义的类”和“父类的泛型参数”。 - 不存在你说的“黑魔法属性”:C#编译器没有提供这类扩展点,没法通过自定义属性让它自动推断泛型参数。
现有写法的必要性
你现在要求第三方写class Fizz : Foo<Fizz>,其实是递归泛型约束的标准用法,虽然看起来重复,但这是目前唯一能确保T严格等于子类本身的方式。比如你可以把Foo<T>的定义强化一下:
abstract class Foo<T> : Bar<T> where T : Foo<T>
这样能避免第三方错误地传入其他类型作为T,但还是得手动写两次类名。
替代优化思路
如果实在想简化第三方的写法,可以考虑用Roslyn源代码生成器:你可以写一个生成器,让第三方只需要标记class Fizz : Foo,生成器自动帮他们补全成class Fizz : Foo<Fizz>。不过这需要额外的工具开发,属于工程层面的优化,不是语言原生特性。
总的来说,目前没有办法完全消除这个重复的类名,这是C#泛型系统的设计限制——编译器无法在定义子类时自动推断父类的泛型参数为子类本身。
内容的提问来源于stack exchange,提问作者Yakitawa
相关产品推荐
相关产品推荐

