Подтвердить что ты не робот

Sbyte [] может быть магически отброшен в байт []

Я не уверен, является ли это ошибкой .NET, но я нахожу это действительно интересным.

Как и ожидалось, я не могу этого сделать:

sbyte[] sbytes = { 1, 2, 3 };
byte[] bytes = sbytes; // fails: cannot convert source type 'sbyte[]' to taget type 'byte[]'

Однако, если тип sbytes равен object, это работает:

object obj = new sbyte[]{ 1, 2, 3 };
byte[] bytes = obj as byte[];
Assert.IsNull(bytes, "WTF??")

Замечание 1: та же проблема возникает для int[] - uint[] и других примитивных типов.

Замечание 2. Хотя код обрабатывает массив как byte[], отладчик теряет фокус и показывает ? -s в массиве.

screenshot

Примечание 3. Это работает только для массивов, а не для самих базовых типов:

object sbyteObj = (sbyte)1;
byte byteObj = (byte)sbyteObj; // System.InvalidCastException: Specified cast is not valid.

Хорошо, конечно, я могу проверить тип следующим образом:

if (obj.GetType() == typeof(byte[]))

Является ли это предполагаемым поведением оператора as и прямого каста, или это ошибка .NET?

4b9b3361

Ответ 1

Нет, это не ошибка. Это просто несоответствие импеданса между правилами языка С# (которые утверждают, что нет доступных преобразований) и правилами CLR (где доступно преобразование).

Обратите внимание, что компилятор действительно, действительно думает, что он лучше знает:

byte[] bytes = new byte[10];
// error CS0030: Cannot convert type 'byte[]' to 'sbyte[]'
sbyte[] sbytes = (sbyte[]) bytes; 

И даже если у вас есть код, который компилируется с предупреждением, он действительно не делает то, что он говорит:

byte[] bytes = new byte[10];
// warning CS0184: The given expression is never of the provided ('sbyte[]')
if (bytes is sbyte[])
{
    Console.WriteLine("Yes");
}

Запустите этот код, и вы не получите вывод... но если вы просто измените тип времени компиляции bytes, он напечатает Да:

object bytes = new byte[10];
// No warning now
if (bytes is sbyte[])
{
    Console.WriteLine("Yes"); // This is reached
}