C#中如何定义接受泛型类型的泛型接口?
在C#中实现泛型接口接受泛型类型参数的方案
C#不支持直接将T<>作为泛型接口的参数,但可以通过开放构造泛型类型约束(C# 7.3及以上版本支持)来实现你的需求。核心思路是先定义一个泛型标记接口,约束目标泛型类(Mock、Provider)实现它,再让MyConfigs的泛型参数约束为这个标记接口的开放构造类型,这样就能在接口中使用T<CustomerConfig>这类写法。
最优实现方案(C# 7.3+)
// 定义泛型标记接口,约束所有需要作为MyConfigs参数的泛型类实现它 public interface IGenericWrapper<T> { } // 你的Mock类,实现标记接口 public class Mock<T> : IGenericWrapper<T> { public void Setup() { } } // 你的Provider类,实现标记接口 public class Provider<T> : IGenericWrapper<T> { public T Get() => default!; } // 定义核心的MyConfigs接口,泛型参数T被约束为IGenericWrapper的开放构造类型 public interface MyConfigs<T> where T : IGenericWrapper<> { T<CustomerConfig> Customer { get; } T<SupplierConfig> Supplier { get; } } // 继承得到Mocks接口,自动拥有Customer和Supplier属性,返回类型为Mock<...> public interface Mocks : MyConfigs<Mock> { } // 继承得到Providers接口,属性返回类型为Provider<...> public interface Providers : MyConfigs<Provider> { } // 配置类定义 public class CustomerConfig { } public class SupplierConfig { }
方案说明
IGenericWrapper<T>是一个标记接口,无需实现任何方法,仅用于约束MyConfigs的泛型参数必须是接受单个类型参数的泛型类型。where T : IGenericWrapper<>约束指定T必须是IGenericWrapper的开放构造类型(即未指定具体类型参数的泛型类型),因此可以在MyConfigs中用T<CustomerConfig>声明属性的返回类型。- 继承后的
Mocks和Providers接口会自动继承属性定义,返回类型分别对应Mock<CustomerConfig>/Mock<SupplierConfig>和Provider<CustomerConfig>/Provider<SupplierConfig>,完全满足“统一属性名称、差异化返回类型”的需求。
兼容旧版C#的替代方案
如果你的项目使用C# 7.3之前的版本,可以通过显式接口覆盖实现需求:
// 定义泛型接口,封装属性返回类型的公共行为(可选) public interface IConfigContainer<TConfig> { } public class Mock<T> : IConfigContainer<T> { public void Setup() { } } public class Provider<T> : IConfigContainer<T> { public T Get() => default!; } // 定义基接口,统一属性名称 public interface MyConfigs { IConfigContainer<CustomerConfig> Customer { get; } IConfigContainer<SupplierConfig> Supplier { get; } } // 继承时显式指定具体返回类型 public interface Mocks : MyConfigs { new Mock<CustomerConfig> Customer { get; } new Mock<SupplierConfig> Supplier { get; } } public interface Providers : MyConfigs { new Provider<CustomerConfig> Customer { get; } new Provider<SupplierConfig> Supplier { get; } }
替代方案说明
- 通过
new关键字覆盖基接口的属性类型,虽然代码量略多,但兼容更早的C#版本。 - 若需要多态性,可以通过
MyConfigs接口访问属性;若需要调用具体类型的方法(如Mock.Setup、Provider.Get),则需转换为具体类型,或在IConfigContainer中定义公共方法。
内容的提问来源于stack exchange,提问作者scotilen
相关产品推荐
相关产品推荐

