Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 762
Sriram Sakthivel Avatar asked Jul 14 '13 15:07

Sriram Sakthivel


1 Answers

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.

like image 90
Jeppe Stig Nielsen Avatar answered Oct 19 '22 15:10

Jeppe Stig Nielsen