对于C#,是否可以在泛型类的实例声明中指定类型约束?

Mar*_*ver 2 c# generics types

我想带两个具有共享层次结构的对象,它们都实现一个接口,并将它们放在一个容器中,例如List,它通常采用单个类型的参数.我在这个问题中使用了非编译代码,因为我找不到C#的一个功能,它可以让我在编译时做我想问的事情.

所以,设置如:

public class DataObject
{
    int property;
}

public interface IWriteData
{
    void WriteData();
}

public class A : DataObject, IWriteData, IDoSomethingElseA
public class B : DataObject, IWriteData, IDoSomethingElseB
Run Code Online (Sandbox Code Playgroud)

和代码:

var x = new A();
var y = new B();
List<T> where T : (DataObject, IWriteData) mySharedContainer = new List<T>;
T.Add(x);
T.Add(y);
Run Code Online (Sandbox Code Playgroud)

上面的列表声明行不起作用,但是我能想到的最接近我的目标.我的预感是,这不是目前能够完成的事情,我需要:

  • 定义一个他们可以继承的共享类,并且还实现了接口(在这种情况下我不想做,因为这不是我的代码库,我试图尽可能减小占用空间)
  • 做运行时类型转换,并失去编译时类型检查的好处
  • 通过编写处理类型A的代码和处理类型B的代码来重复代码.

但是,我会非常高兴地发现其他情况.在考虑它时,我看不出任何直接的理由,理论上,编译器无法在该行说"好吧,从现在开始我将检查添加到此列表的所有内容是否继承自该类并实现这些接口".

谢谢!

Eri*_*ert 8

您想要的功能称为交集类型,C#对交集类型的支持非常非常有限.实际上只有一种方法可以指定类似的类型限制,它是这样的:

class C 
{
    public static void M<T>(T t) where T : DataObject, IWriteData 
    {
        List<T> myList = new List<T>() { t };
        // With this restriction we can make both these conversions:
        IEnumerable<DataObject> iedo = myList; // Legal
        IEnumerable<IWriteData> iewd = myList; // Legal 
    }
}
Run Code Online (Sandbox Code Playgroud)

T仅限于在实现的类型和扩展类型的交集中的类型.IWriteDataDataObject

但这并不能解决你遇到的问题.在这个解决方案中,我们可以调用M<A>M<B>获取一个列表,T其中T肯定是两者DataObjectIWriteData.但你必须是什么T.T可以是A,或者B,但T不能是" A或者B".(并且"A或B"将是联合类型.)

在考虑它时,我看不出任何直接原因,理论上,编译器无法在该行说"好了,从现在开始我将检查添加到此列表的所有内容是否继承自该对象类并实现这些接口".

(对象是类的实例;类扩展类,而不是对象.)

你是对的; 没有理论上的理由.有些语言支持union和intersection类型; Hack,我现在使用的语言,就是这样一种语言.TypeScript也支持这种类型的输入.但是C#不是其中之一,对不起.

  • @Joao:不,工会和交集是对立的.联合类型"A | B"是类型限制"类型匹配限制A是可接受的或类型匹配限制B是可接受的".交集类型"A&B"是类型限制"只有匹配限制A和B的类型是可接受的". (2认同)