如何声明函数参数以接受泛型抽象基类的所有派生类型?
解决方法
你的问题出在C#泛型的不变性上:默认情况下,泛型类InputModelBase<T>是不变的——即使SearchParameters继承自InputModelParametersBase,InputModelBase<SearchParameters>也不能隐式转换为InputModelBase<InputModelParametersBase>,所以直接传SearchInput会报错。
下面提供两种可行的解决方案:
方案一:使用泛型方法
给someFunction添加泛型参数,并加上类型约束,让它能接受任意符合条件的InputModelBase<T>派生类型:
public void someFunction<T>(InputModelBase<T> oInputParams) where T : InputModelParametersBase { // 这里编写你的方法逻辑 }
调用时无需显式指定泛型类型,编译器会自动推断:
var oSearchInput = new SearchInput(); someFunction(oSearchInput); // 正常编译通过
这种方案无需修改现有的类结构,简单直接,适合大多数场景。
方案二:使用协变接口
如果需要统一方法参数的类型(比如在集合、依赖注入等场景),可以通过协变接口实现。C#中只有接口和委托支持协变/逆变,具体步骤如下:
- 定义一个带
out关键字的协变接口(out表示T只能作为返回值,不能作为方法参数):
public interface IInputModelBase<out T> where T : InputModelParametersBase { string Token { get; } bool Trace { get; } T Parameters { get; } }
- 修改基类
InputModelBase<T>,让它实现这个接口:
[DataContract] public abstract class InputModelBase<T> : IInputModelBase<T> where T : InputModelParametersBase { [DataMember] public string Token { get; set; } [DataMember] public bool Trace { get; set; } [DataMember(Name = "parameters")] public T Parameters { get; set; } }
- 重新声明
someFunction,参数类型改为协变接口:
public void someFunction(IInputModelBase<InputModelParametersBase> oInputParams) { // 方法逻辑 }
此时调用someFunction(oSearchInput)就能正常编译,因为协变允许将IInputModelBase<SearchParameters>隐式转换为IInputModelBase<InputModelParametersBase>。
内容的提问来源于stack exchange,提问作者FDB
相关产品推荐
相关产品推荐

