如果我有:
public class A { public int a1;}
public class B : A { public int b1;}
void myFunc(A a)
{}
static void Main(string[] args)
{
B b = new B();
myFunc(b);
}
<{1>}中的,myFunc
可以访问a
个对象,但它只能引用(无需强制转换)内存中b
的区域。
这是理解的。
在协方差中,似乎type A
也可以访问a
:
正如您所看到的 - 它接受b
的可枚举,并且仍然可以访问其A
类型的对象
的问题:
1 )好的,幕后工作如何? B
引用如何向我显示A
对象?
2 )如果我想在函数中看到larger
类的a1
属性,该怎么办?
协方差相关:
在C#4之前,你无法传递List: 无法转换 'System.Collections.Generic.List'到 'System.Collections.Generic.IEnumerable'
答案 0 :(得分:6)
A引用如何能够向我显示更大的对象?
首先,它是较小的类型。每只长颈鹿都是动物,但不是每只动物都是长颈鹿。因此,世界上长颈鹿的数量比世界上的动物少。因此,长颈鹿是一种比动物更小的类型。
您的类型B是较小的类型而不是A.当然,对较大类型的引用可以引用较小类型的内容。
这与协方差无关。 IEnumerable<A>
始终可以为您提供B
:
List<A> myList = new List<A>() { new B(); } // No covariance here
Console.WriteLine(myList[0].GetType()); // it's a B.
动物名单中可以包含长颈鹿。这与协方差无关。
同样,引用总是可以为您提供较小的类型:
A a = new B(); // Legal!
那些说它与协方差无关的人......
A的序列包含 a B与协方差无关。与协方差有关的是 B序列可以通过引用转换转换为A序列。在将协变转换添加到C#4之前,该转换将失败。
如果我想在函数中看到A类的a1属性怎么办?我应该改变什么?
你不应该改变任何东西;它已经有效了。试试吧。
答案 1 :(得分:5)
如您所见 - 它接受A的Enumerable,它仍然可以访问其B类型的对象
调试器将其显示为B,因为它看到它的实际类型是B. myFunc
中的代码只能访问A的成员,除非它将对象强制转换为B.
答案 2 :(得分:0)
myFunc会看到类型B,因为您使用myFunc(b);
你在基类A中看到a1
如果你这样做
static void Main(string[] args)
{
A a = new A();
myFunc(a);
}
你会直接看到A型
修改强>
为了说清楚:
void myFunc(A a)
应该读作
void myFunc({Either A or something "larger" than A} a)
“较大”意味着“继承”