多种类型作为单个通用参数

时间:2017-05-16 20:14:26

标签: c# generics

有一个抽象类和接口:

public abstract class Foo
{
    public void DoFoo();
}
public interface IBar
{
     void DoBar();
}

我有多个从Foo继承的类,但并非所有类都实现了IBar。我可以声明将被限制为Foo和IBar的泛型类,如下所示:

public class Test<T> where T : Foo, IBar
{
    public List<T> ListOfFooThatImplementsIBar;
}

但我想定义一个简单的集合,它将受到Foo和IBar的限制,如下所示:

List<Foo and IBar> myList = new List<Foo and IBar>();

有没有办法在C#中很好地完成这项工作?

2 个答案:

答案 0 :(得分:9)

  

有没有办法在C#中很好地完成这项工作?

没有

您想要的功能称为&#34; intersection types&#34;。 C#仅支持&#34;其中&#34;条款。这总是让我觉得有些奇怪。

也很奇怪:我每天都和C#泛型系统的设计师交谈,我从来没有想过要问他在一个地方只有交叉类型的设计原则是什么。也许明天我会解决这个问题!

许多语言或多或少地支持交集类型 - 想到Hack和Flow。有趣的是,这两者都使用基于流的打字。交叉和联合类型在很多方面都非常适合基于流的输入。

答案 1 :(得分:1)

正如@EricLippert回答的那样,没有办法像我想要的那样完全按照它做出来。这个问题有几种解决方法:

  1. 与Foo和IBar建立通用接口(如果Foo类是第三方类,可能不适用,并且您不能影响其来源,如我的情况)
  2. 使用原始列表作为List&lt;对象&gt;并在需要时执行运行时转换(这可能会降低性能)。
  3. 我选择最适合我需要的第三个:

    public List<(Foo, IBar)> ListOfFooThatImplementsIBar;
    
    public void Add<T>(T item) where T : Foo, IBar { ListOfFooThatImplementsIBar.Add((item, item)); }
    

    所以当我需要与Foo交互时,我可以使用Item1,Item2与IBar交互。 希望我的回答有所帮助!