C#是具有generics类型约束的generics类型

让我们假设一个界面

interface IOwnedBy where T : IOwner { T Owner { get; } } 

 interface IOwner { public int Id { get; } } 

在我的代码的某处,我想做以下事情:

 if (obj is OwnedBy) { DoSomethingWith( obj.Owner.Id ); } 

基本上,我想检查obj是否是任何OwnedBy实现。 由于IOwner是任何generics参数的类型约束,我认为这个可行。 但这种情况从未得到满足。

没有使用很多reflection的任何方式?

将接口更改为T协变:

 interface IOwnedBy where T : IOwner { T Owner { get; } } 

obj is OwnedBy失败,因为编译器无法知道它是否安全 ; IOwnedBy被声明为不变量。 如果你明确地告诉编译器它是协变的,那么它就知道转换是安全的并且它将起作用。

为什么在不变的界面中它不安全? 考虑以下:

 interface IOwnedBy where T : IOwner { T Owner { get; } void SetOwner(T Owner); } class Person: IOwner { } class Cat: IOwner { } Cat tom = ... IOwnedBy owned = ... var nope = owned as IOwnedBy; nope.SetOwner(tom); //Ouch! Just set a cat as an owner of a IOwnedBy