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?
Ответы
Ответ 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
}