Can a String[] hold System.Object inside it?

徘徊边缘 提交于 2019-12-18 13:13:58

问题


Do you feel question is strange? yes what happened also strange. let me explain.

I have found a snippet from this Covariance and Contravariance with C# Arrays

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

Jon skeet explains that above code will throw ArrayTypeMismatchException, as said yes it does.

what I did is I put a breakpoint in line 3, Using DebuggerVisualizer I manually set objects[0] = new object() it doesn't throw any error and it works. later checking strings[0].GetType() returns System.Object. not only System.Object any type can be set in string[] by above mentioned procedure.

I have no idea how this happened i raised my question as a comment over there in the very same question i saw this but no answers.

Am curious to know what is happening behind. Anybody explain pls.

Edit1 This is even Interesting

After reproducing the above behaviour try this

int len = strings[0].Length;

if you place mouse over the Property Length is says strings[0].Length threw ArgumentException with message Cannot find the method on the object instance but actually it doesnt throw exception and code runs yielding result len=0


回答1:


Your example seems to answer the question: yes, a string reference can refer a non-string object. This is not intended, however.

Consider what you have found, a bug in the debugger.

As Jon Skeet explains in the answer you mention, because .NET arrays have this "crazy" covaraiance even though arrays are not read-only but more like read-write, everytime one writes to an array of references the framework has to check the type of the object one tries to write to the array, and throw an ArrayTypeMismatchException if you're about to use a wrong type, like assigning an instance of Cat to an array of Dogs (a runtime Dog[]) which has been cast by "crazy" covariance into an Animal[].

What you have demonstrated is that when we use the Immediate window of the Visual Studio debugger (or similar windows), this required type check is not done, and as a result this can lead to any type Y (except pointer types probably) being assigned to a reference type variable of any reference type X. Like this:

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

This can make a Cat bark like a Dog, and stuff like that.

In the linked thread on Bypassing type safeguards, the answer by CodesInChaos shows an unrelated technique with which you can put a reference to an object of a "wrong" and unrelated type into a reference variable.




回答2:


(I have preferred to rewrite my answer because the previous one had too many updates and wasn't clear enough).

Apparently, it has been found a not-so-perfect behaviour in one of the tools (Immediate Window) in the VS debugging part. This behaviour does not affect (AT ALL) the normal execution of the code and, purely speaking, does not affect even the debugging process.

What I meant in the last sentence above is that, when I debug code, I never use the Immediate Window, just write any code I want, execute it and see what the debugger shows. The referred problem does not affect this process (which can be called "debugging actually-executed code"; in the proposed example, pressing F11 when you are on objects[0] = new object();), what would imply a serious problem in VS. Thus from my point of view (the kind of debugging I do) and from the execution point of view, the referred error has no effect at all.

The only application of this error is when executing the "Immediate Window" functionality, a feature of the debugger which estimates what the code will deliver before it actually delivers it (what might be called "debugging not-executed code" or "estimating expected outputs from non-executed code", etc.; in the proposed example, being on line objects[0] = new object();, not pressing F11 but using the Immediate Window to input values and let this feature to tell you what is expected to happen).

In summary, the referred problem has to be understood within the right context, that is, it is not an overall-applicable problem, not even a problem in the whole debugger (when you press F11 in the referred line from the debugger, it outputs an error and thus the debugger does understand perfectly that this situation is wrong), but just in one of its tools. I am not even sure if this behaviour is even acceptable for this tool (i.e., what "Immediate Window" delivers is a prediction which might not be 100% right; if you want to know for sure what will happen, execute the code and let the debugger show you the information).

  • QUESTION: Can a String[] hold System.Object inside it?
  • ANSWER: NO.
  • CLARIFICATION: covariance is a complex reality which might not be perfectly accounted by some of the secondary tools in VS (e.g., "Immediate Window") and thus there might be cases where the aforementioned statement does not fully apply. BUT this is a local behaviour/bug in the specific tool with no effect in the actual execution of the code.


来源:https://stackoverflow.com/questions/17640882/can-a-string-hold-system-object-inside-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!