结果是类型的交集?

gre*_*man 2 c# generics types

有关记录:类型的并集与交集,请参阅:TypeScript 中的高级类型

假设我有接口IA和IB. 创建这些参数的交集作为参数非常容易,而无需创建额外的接口。

void Foo<T>(T t) where T : IA, IB
Run Code Online (Sandbox Code Playgroud)

但是,当结果应该是类型的交集时,我看不到执行相同操作的明确方法。考虑提供商/工厂场景:

interface IProvider
{
  T Provide();
}
Run Code Online (Sandbox Code Playgroud)

稍后消费者将获得该提供者:

void Consume(IProvider provider)
Run Code Online (Sandbox Code Playgroud)

问题是如何定义T。如果我定义它使Provide方法通用:

T Provide<T>() where ...
Run Code Online (Sandbox Code Playgroud)

这是没有意义的,因为这意味着消费者能够以某种方式告诉现有的提供者它提供什么类型。

如果我将整个提供程序定义为泛型类型:

interface IProvider<T> where ...
{
  T Provide();
}
Run Code Online (Sandbox Code Playgroud)

它更有意义,但现在该方法也Consume必须是通用的,并且需要为联合定义通用约束,开始“泄漏”很快使代码变得丑陋。

那么有没有一种方法可以干净、正确地表达它呢?就像输入交集时一样——简短、干净且正确。

更新:作为一种解决方法,我现在使用Intersection提供类型检查的类型,但代价是额外的内存消耗。

sta*_*ica 5

TL;DR:我很遗憾地告诉您,您所要求的 — 使用方法返回类型的交集类型 — 在 C# 中根本不可能。类型系统不够复杂。

您可能会发现我的软件工程 SE 问题“哪些静态类型语言支持函数返回值的交集类型?” 出于兴趣。我很惊讶地发现 Java 在这方面优于 C#。

C# 中的交集类型(“两者A和B”):

  • 可以使用泛型的方法参数:

    void Method<T>(T parameter) where T : A, B
    
    Run Code Online (Sandbox Code Playgroud)
  • 方法返回类型不可能。(当然,您可以诉诸后期绑定技巧,例如使用/ Castle DynamicProxydynamic动态创建匹配的交集类型(通常在 Moq 等模拟框架中用于动态生成类型);我只是看看这个答案中静态类型/类型系统的可能性。)System.Reflection.Emit

C# 中的联合类型(“要么A或B”):

  • 可以使用多种语言机制的方法参数:

  • 可以使用某种通用的、可区分的类似联合类型来伪造返回值Either<A, B>。