积极答复者
数组直接赋值问题

问题
-
int[] n = { 1, 2, 3 };object[] o = n; //为什么这样不可以?以上赋值不可以,但是下面的赋值却可以:(Chinese类是Person类的子类)Chinese[] cn = { new Chinese() { Name = "zs" }, new Chinese() { Name = "ls" } };Person[] per = cn;//为什么这样可以?数组不都是引用类型吗?object[] o=n;却不可以求解释。不要只来一句:int是值类型,Chinese是引用类型。
- 已移动 Paul Zhou 2011年4月26日 10:38 C# (发件人:.NET Framework 一般性问题讨论区)
答案
-
-
这是个非常好的问题。这里涉及到有关协变 (Covariance) 的问题。
所谓协变,就是指如果存在两个引用类型 A 和 B,如果 A > B (也就是 B 属于 A 的派生类),有开放类型 C<T>,且从封闭类型 C<B> 到 C<A> 的转换合法,那么就成类型 C<T> 支持协变。记作 C<out T> 或 C<T+>。
在 .NET 2.0 和 3.5 中,数据可以“看成”是 Array<T>,其中 T 为数组的元素类型,.NET 2.0 / 3.5 支持数组的隐式协变,也就是说,如果存在下面的代码:
public class A { }
public class B { }
A[] a;
B[] b;
a = b;是完全可以执行的。这里 A > B,A[] 和 B[] 可以看作是 Array<A> 和 Array<B>。(这里我不想讨论关于 CLR 对数组的处理,为了简化,就用 Array<T> 代替)。
注意,因为协变只支持引用类型,因此,从值类型到引用类型的协变不支持。比如从 int[] 到 object[]。这就解释了您提出的上面的问题。
进一步,如果 A < B,对于开放类型 C<T>,C<B> 到 C<A> 的转换合法,那么这个就叫逆变 (contravariance),记作 C<in T> 或者 C<T->。
协变和逆变在 C# 4.0 的接口和委托中适用。对于其他类型,如数组以及部分委托,仍使用 C# 2.0 / 3.5 的隐式协变。
要了解更多的协变/逆变的信息,可以参考我写的 PPT,http://www.markzhou.com/blog/page/Tech-Talk.aspx,然后下载 201003 的 PPT 或者代码。
Series Number Presenter Topic PowerPoint Presentation Video Source Code 201020 Mark Zhou ASP.NET MVC, Part 4 Download Download 201019 Mark Zhou ASP.NET MVC, Part 3 Download Download 201017 Mark Zhou ASP.NET MVC, Part 2 201015 Mark Zhou ASP.NET MVC, Part 1 Download 201008 Mark Zhou C#: Generics Download Download 201006 Mark Zhou C#: Inside Operator Overloading Download 201005 Mark Zhou C#: Operator Overloading Download Download 201003 Mark Zhou C#: Covariance and contravariance Download Download
Mark Zhou- 已标记为答案 Leo Liu - MSFTModerator 2011年4月29日 2:37
全部回复
-
移至C#论坛寻求更好的支持
Paul Zhou [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
-
这是个非常好的问题。这里涉及到有关协变 (Covariance) 的问题。
所谓协变,就是指如果存在两个引用类型 A 和 B,如果 A > B (也就是 B 属于 A 的派生类),有开放类型 C<T>,且从封闭类型 C<B> 到 C<A> 的转换合法,那么就成类型 C<T> 支持协变。记作 C<out T> 或 C<T+>。
在 .NET 2.0 和 3.5 中,数据可以“看成”是 Array<T>,其中 T 为数组的元素类型,.NET 2.0 / 3.5 支持数组的隐式协变,也就是说,如果存在下面的代码:
public class A { }
public class B { }
A[] a;
B[] b;
a = b;是完全可以执行的。这里 A > B,A[] 和 B[] 可以看作是 Array<A> 和 Array<B>。(这里我不想讨论关于 CLR 对数组的处理,为了简化,就用 Array<T> 代替)。
注意,因为协变只支持引用类型,因此,从值类型到引用类型的协变不支持。比如从 int[] 到 object[]。这就解释了您提出的上面的问题。
进一步,如果 A < B,对于开放类型 C<T>,C<B> 到 C<A> 的转换合法,那么这个就叫逆变 (contravariance),记作 C<in T> 或者 C<T->。
协变和逆变在 C# 4.0 的接口和委托中适用。对于其他类型,如数组以及部分委托,仍使用 C# 2.0 / 3.5 的隐式协变。
要了解更多的协变/逆变的信息,可以参考我写的 PPT,http://www.markzhou.com/blog/page/Tech-Talk.aspx,然后下载 201003 的 PPT 或者代码。
Series Number Presenter Topic PowerPoint Presentation Video Source Code 201020 Mark Zhou ASP.NET MVC, Part 4 Download Download 201019 Mark Zhou ASP.NET MVC, Part 3 Download Download 201017 Mark Zhou ASP.NET MVC, Part 2 201015 Mark Zhou ASP.NET MVC, Part 1 Download 201008 Mark Zhou C#: Generics Download Download 201006 Mark Zhou C#: Inside Operator Overloading Download 201005 Mark Zhou C#: Operator Overloading Download Download 201003 Mark Zhou C#: Covariance and contravariance Download Download
Mark Zhou- 已标记为答案 Leo Liu - MSFTModerator 2011年4月29日 2:37