0

How is this possible:

    DivideByZeroException[,] a = new DivideByZeroException[,] { { new DivideByZeroException() } };
    ArithmeticException[,] b = a;   // a = b; is not possible

while all these:

    typeof(DivideByZeroException[,]).IsInstanceOfType(typeof(ArithmeticException[,]))   // false
    typeof(DivideByZeroException[,]).IsSubclassOf(typeof(ArithmeticException[,]))   // false
    typeof(DivideByZeroException[,]).IsAssignableFrom(typeof(ArithmeticException[,]))   // false
    TypeDescriptor.GetConverter(typeof(DivideByZeroException[,])).CanConvertTo(typeof(ArithmeticException[,]))  // false
    TypeDescriptor.GetConverter(typeof(ArithmeticException[,])).CanConvertFrom(typeof(DivideByZeroException[,]))  // false

return false?

And if so, why is this below not possible?

    int[,] x = new int[,] { { 123 } };
    float[,] y = x;

How does the 2D array casting work in C#?

Is it some hidden implicit operator somewhere? (Can implicit operator be generic?? I thought not!)

Is it a hidden language syntax feature?

If you would be trying to convert the value from one type to another by Reflection (while not understanding the both types), how can you know if the conversion is possible and how would you convert it?

P.W.
  • 657
  • 8
  • 15
  • 4
    https://codeblog.jonskeet.uk/2013/06/22/array-covariance-not-just-ugly-but-slow-too/: *The basic idea is that C# allows a reference conversion from type TDerived[] to type TBase[], so long as: ... TDerived and TBase are both **reference types***. `float` and `int` are not reference types. – dbc Dec 12 '19 at 18:18
  • Maybe duplicate of [Cast an object back to a value type array](https://stackoverflow.com/q/16297069/3744182), [Can't convert value type array to `params object[]`](https://stackoverflow.com/q/9104268/3744182) and/or [Why covariance and contravariance do not support value type](https://stackoverflow.com/q/12454794/3744182)? Agree? – dbc Dec 12 '19 at 18:20
  • [Covariance and Contravariance with C# Arrays](https://stackoverflow.com/q/17619139) and [Why is array co-variance considered so horrible?](https://stackoverflow.com/q/4317459) might also be useful. – dbc Dec 12 '19 at 18:32
  • @dbc Thanks. So I'm guessing it's a language feature. But how would you approach the conversion by Reflection? (When you don't even know the types are arrays?) Is that possible? – P.W. Dec 12 '19 at 18:35
  • Well it's actually built into the runtime from the beginning, then subsequently implemented in c# back around the .Net 1.1 timeframe if I recall correctly. See https://blogs.msdn.microsoft.com/ericlippert/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance/. – dbc Dec 12 '19 at 18:42
  • If your question is actually *how can I invoke a covariant array cast via reflection*? rather than *How is cast X possible while cast Y is not* you might want to rewrite your question to clarify, showing the code where you're stuck. I wouldn't know the answer to this clarified question, but maybe see [Determine if a reflected type can be cast to another reflected type](https://stackoverflow.com/q/292437) and/or [Execute implicit cast at runtime](https://stackoverflow.com/q/7065453). – dbc Dec 12 '19 at 18:43
  • Yes, apart from the simple questions above, I'd like to know how to write a case for 2D arrays converting for a method like `object Convert(object value, Type destType)`, when all standard cases won't work. I can handle all standard types I need with Type.IsAssignable, Type.IsEnum, IConvertible or TypeConverters, but I don't know how to detect 2D arrays compatibillity. I'm not even sure what's the actual class for this, so I could try to decompose and reassemble it. Maybe anyone can give code example for this? PS: The long code from your linked question does not compile (missing class). – P.W. Dec 12 '19 at 19:06
  • 1
    Is this the sort of thing you're looking for? https://dotnetfiddle.net/IoQ3X5 Or are you actually trying to generate the code to do the cast in runtime? – dbc Dec 12 '19 at 19:27
  • @dbc Thanks for the code. Stepping through it I discovered that your IsAssignableFrom (line 41) actually returns true and the `IsAssignableFromAsCovariantArray` method is not even invoked (however it works as well). This made me realize that I've got a bug in my checks (the types are swapped), so there was never a problem at all with Reflection. And this means you can do `object a = new DivideByZeroException[,]` and then `var b = (ArithmeticException[,])a;`! (after checking `typeof(ArithmeticException[,]).IsAssignableFrom(a.GetType())`). Thanks for making me see my mistake. – P.W. Dec 13 '19 at 12:07
  • @dbc PS: if you wish, you can put all the information with your example code into an Answer, so I will up-vote it and I will be able to close this question by accepting the answer. Thanks again. – P.W. Dec 13 '19 at 12:09
  • If `IsAssignableFrom()` actually returns true then this looks like a duplicate of [Can't convert value type array to `params object[]`](https://stackoverflow.com/q/9104268/3744182) and [Covariance and Contravariance with C# Arrays](https://stackoverflow.com/q/17619139/3744182) after all. – dbc Dec 15 '19 at 19:56

0 Answers0