I'm not sure whether this is a .NET bug but I find it really interesting.
As expected, I cannot do this:
sbyte[] sbytes = { 1, 2, 3 };
byte[] bytes = sbytes; // fails: cannot convert source type 'sbyte[]' to taget type 'byte[]'
However, if the type of sbytes
is object
, this works:
object obj = new sbyte[]{ 1, 2, 3 };
byte[] bytes = obj as byte[];
Assert.IsNull(bytes, "WTF??")
Remark 1: The same issue occurs for int[]
- uint[]
and the other primitive types as well.
Remark 2: Though the code handles the array as a byte[]
, the debugger loses the focus and shows ?
-s in the array.
Remark 3: This works only for arrays, not for the underlying types themselves:
object sbyteObj = (sbyte)1;
byte byteObj = (byte)sbyteObj; // System.InvalidCastException: Specified cast is not valid.
Ok, of course I can check the type like this:
if (obj.GetType() == typeof(byte[]))
Is this an intended behavior of the as
operator and direct casting, or is this a .NET bug?
No, it's not a bug. It's just an impedance mismatch between the C# language rules (which claim there's no conversion available) and the CLR rules (where the conversion is available).
Note that the compiler really, really thinks it knows best:
byte[] bytes = new byte[10];
// error CS0030: Cannot convert type 'byte[]' to 'sbyte[]'
sbyte[] sbytes = (sbyte[]) bytes;
And even when you've got code that compiles with a warning, it doesn't really do what it says:
byte[] bytes = new byte[10];
// warning CS0184: The given expression is never of the provided ('sbyte[]')
if (bytes is sbyte[])
{
Console.WriteLine("Yes");
}
Run that code and you don't get output... but if you just change the compile-time type of bytes
, it does print Yes:
object bytes = new byte[10];
// No warning now
if (bytes is sbyte[])
{
Console.WriteLine("Yes"); // This is reached
}
See more on this question at Stackoverflow