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

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

我从C#Arrays中找到了这个Covariance和Contravariance的片段

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但实际上它没有抛出exception并且代码运行产生结果len=0

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

考虑一下你发现的,调试器中的一个错误

正如Jon Skeet在你提到的答案中解释的那样,因为.NET数组具有这种“疯狂”的协同作用,即使数组不是只读但更像是读写,每次写入一个引用数组时,框架必须检查类型一个试图写入数组的对象,如果你要使用一个错误的类型,抛出一个ArrayTypeMismatchException ,比如将一个Cat实例分配给一个Cat的数组(一个运行时Dog[] ) “疯狂”协变成Animal[]

你所演示的是,当我们使用Visual Studio调试器的立即窗口(或类似的窗口)时,这个必需的类型检查没有完成,因此这可能导致任何类型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 

这可以使CatDog一样吠叫,以及类似的东西。

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

(我更喜欢重写我的答案,因为前一个有太多的更新,并且不够清晰)。

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

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

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

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

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