让我们假设一个界面
interface IOwnedBy<T> where T : IOwner
{
T Owner { get; }
}
和
interface IOwner
{
public int Id { get; }
}
在我的代码中的某处,我想执行以下操作:
if (obj is OwnedBy<IOwner>)
{
DoSomethingWith( obj.Owner.Id );
}
基本上,我想检查obj是否是任何OwnedBy实现。由于IOwner是任何泛型参数的类型约束,我认为这个可行。但这种情况从未得到满足。
没有使用很多反射的任何方式?
答案 0 :(得分:7)
将界面更改为T
中的协变:
interface IOwnedBy<out T> where T : IOwner
{
T Owner { get; }
}
obj is OwnedBy<IOwner>
失败,因为编译器无法知道其安全; IOwnedBy
被声明为不变量。如果你明确地告诉编译器它是协变的,那么知道转换是安全的并且它将起作用。
为什么在不变的界面中它不安全?请考虑以下事项:
interface IOwnedBy<T> where T : IOwner
{
T Owner { get; }
void SetOwner(T Owner);
}
class Person: IOwner { }
class Cat: IOwner { }
Cat tom = ...
IOwnedBy<Person> owned = ...
var nope = owned as IOwnedBy<IOwner>;
nope.SetOwner(tom); //Ouch! Just set a cat as an owner of a IOwnedBy<Person>