提前道歉,因为这个微不足道的问题,但我很困惑
我有一个类层次结构如下
namespace MyNamespace
{
public class ClassA {}
public class TypeA<A> where A : ClassA
{
public A p1 { get; set; }
}
public class SubTypeA<A> : TypeA<A> where A : ClassA
{
public TypeA<A> p2 { get; set; }
public void foo()
{
var x = new TypeA<ClassA>();
var y = (TypeA<ClassA>) p2;
}
}
}
为什么C#将p2
强制转换为TypeA<ClassA>
,而p2
是TypeA<A>
的实例,其中A
的类型为ClassA
}?
由于
答案 0 :(得分:3)
您正在寻找covariance,这在课程中不受支持,但在接口和代理中也是如此。
按如下方式设计界面:
public interface ITypeA<out A>
where A : ClassA
{
A p1
{
get;
}
}
public class ClassA
{
}
public class TypeA<A> : ITypeA<A> where A : ClassA
{
public A p1
{
get;
set;
}
}
public class SubTypeA<A> : TypeA<A> where A : ClassA
{
public TypeA<A> p2
{
get;
set;
}
public void foo()
{
var x = new TypeA<ClassA>();
ITypeA<ClassA> y = p2;
}
}
这里的缺点是协变泛型类型的属性如果可以设置则无效。
我想建议您不要在任何地方使用类型推断而不是显式输入。
在您的问题中查看以下句子:
var y = (TypeA<ClassA>)p2;
如果你能够完成整个演员表(因为你可以在没有协方差的情况下测试自己),你可以使用显式强制转换来提供变量的类型,同时可以更好地表达为如下:
// Implicit cast
TypeA<ClassA> y = p2;
隐式类型推断并不总是更具可读性,不应该用于指定类型,因为C#可以显式定义给定引用声明的类型......
这就是我的答案背后没有使用明确演员的原因:
ITypeA<ClassA> y = p2;