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.
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
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 Dog
s (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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With