String []可以在其中保存System.Object吗?

时间:2013-07-14 15:40:25

标签: c# arrays covariance

你觉得问题很奇怪吗?是的,发生的事也很奇怪。让我解释一下。

我找到了此Covariance and Contravariance with C# Arrays

的摘录
string[] strings = new string[1];
object[] objects = strings;
objects[0] = new object();

Jon skeet解释说,上面的代码会抛出ArrayTypeMismatchException,正如所说的那样。

我做的是在第3行放置一个断点,使用DebuggerVisualizer我手动设置objects[0] = new object()它不会抛出任何错误而且它有效。稍后检查strings[0].GetType()将返回System.Object。不仅System.Object可以通过上述过程在string []中设置任何类型。

我不知道这是怎么发生的我在那里提出了我的问题作为评论我在同一个问题中看到了这个但没有答案。

很想知道背后发生了什么。有人解释一下。

Edit1这甚至是有趣的

重现上述行为后,试试这个

int len = strings[0].Length;

如果将鼠标置于属性长度上,则strings[0].Length threw ArgumentException显示消息Cannot find the method on the object instance,但实际上它不会抛出异常并且代码运行会产生结果len=0

2 个答案:

答案 0 :(得分:1)

您的示例似乎回答了这个问题:是的,string引用可以引用非字符串对象。但是,这不是预期的。

考虑您在调试器中找到的内容一个错误

正如Jon Skeet在the answer you mention中解释的那样,因为.NET数组具有这种“疯狂”的协同作用,即使数组不是只读但更像是读写,每次时一个引用数组,框架必须检查尝试写入数组的对象的类型,如果您要使用错误的类型,则抛出ArrayTypeMismatchException,例如分配{{1}的实例}到一个Cat s(运行时Dog)数组,它由“疯狂”协方差转换为Dog[]

您所演示的是,当我们使用Visual Studio调试器(或类似窗口)的立即窗口时,不会执行此必需的类型检查,因此这可能导致任何类型Animal[](除了指针类型(可能)被分配给任何引用类型 Y的引用类型变量。像这样:

X

这可以使X[] arrayOfX = new X[1]; object[] arrayCastByCrazyCovariance = arrayOfX; Y badObject = new Y(); // or another constructor or method to get a Y // Set breakpoint here. // In Immediate window assign: arrayCastByCrazyCovariance[0] = badObject // Detach debugger again. X anomalousReferenceVariable = arrayOfX[0]; anomalousReferenceVariable.MemberOfX(); // or other bad things Cat这样的树皮,以及类似的东西。

在Bypassing类型安全措施的链接线程中,CodesInChaos的答案显示了一种不相关的技术,您可以使用该技术将对“错误”和不相关类型的对象的引用放入引用变量。

答案 1 :(得分:0)

(我更倾向于重写我的答案,因为之前的答案有太多更新而且不够清晰。)

显然,在VS调试部分的一个工具(立即窗口)中发现了一个不那么完美的行为。此行为不会影响(AT ALL)代码的正常执行,纯粹来说,甚至不会影响调试过程。

我在上面的句子中的含义是,当我调试代码时,我从不使用立即窗口,只需编写我想要的任何代码,执行它并查看调试器显示的内容。引用的问题不会影响这个过程(可以称之为“调试实际执行的代码”;在建议的示例中,当您在objects[0] = new object();时按F11),这意味着VS中存在严重问题。因此,从我的观点(我做的调试类型)和从执行的角度来看,引用的错误根本没有效果。

此错误的唯一应用是执行“立即窗口”功能,这是调试器的一项功能,用于估计代码在实际传送之前将提供的内容(可能称为“调试未执行代码”或“估计未执行代码的预期输出“等等;在提议的示例中,在线objects[0] = new object();,不按F11,而是使用立即窗口输入值,并让此功能告诉您预期会发生什么)。

总之,必须在正确的上下文中理解所引用的问题,也就是说,它不是整体适用的问题,甚至不是整个调试器中的问题(当您从调试器的引用行中按F11时) ,它输出一个错误,因此调试器确实完全理解这种情况是错误的),但只是在其中一个工具中。我甚至不确定这个行为是否可以接受这个工具(即,“立即窗口”提供的是一个可能不是100%正确的预测;如果你想知道将会发生什么,请执行代码并让调试器显示信息)。

  • 问题:String []可以在其中保存System.Object吗?
  • 答案:没有。
  • 澄清:协方差是一个复杂的现实,VS中的一些辅助工具可能无法完全解释(例如, “立即窗口”)因而可能存在这样的情况 上述声明并不完全适用。但这是一个本地人 特定工具中的行为/错误对实际没有影响 执行代码。