【问题标题】:Why are the rules that govern whether it's possible to type cast between signed and unsigned integer types so inconsistent?为什么控制是否可以在有符号和无符号整数类型之间进行类型转换的规则如此不一致?
【发布时间】:2016-12-05 21:58:12
【问题描述】:

在 C# 中,在有符号和无符号整数类型之间进行转换的能力似乎受到以下因素的影响:

  1. 是否正在转换标量或数组类型。
  2. 变量是否声明为object

考虑以下代码示例:

// If the variable is declared as a byte array then type casting to sbyte[] results in a 
// compile-time error.
byte[] byteArray = new byte[2];
var c = (sbyte[])byteArray; // Compilation eror

// But if the variable is declared as an object then we neither get a compile-time nor a 
// run-time error
object byteArrayObject = new byte[2];
var a = (sbyte[])byteArrayObject;

// With an explicitly typed scalar, the byte -> sbyte type conversion succeeds with no errors
byte scalarByte = 255;
var b = (sbyte)scalarByte;

// But if the scalar is declared as an object, an InvalidCastException is thrown at run-time
object byteObject = (byte)4;
var e = (sbyte)byteObject; // InvalidCastException

总结一下:

  • 数组声明为字节[]:失败
  • 数组声明为对象:成功
  • 标量声明为字节:成功
  • 标量声明为对象:失败

虽然此示例仅考虑字节,但相同的模式似乎适用于其他整数类型。谁能解释为什么这些结果如此不一致?

【问题讨论】:

标签: c# .net


【解决方案1】:

第二种情况与有符号或无符号类型无关。您根本无法将值类型拆箱为不是其确切类型的东西。这也会失败:

object i = 1;
var l = (long)i; //Runtime expection: unboxing an int to a long

第一种情况是 C# 和 CLR 中允许的转换之间不幸的不匹配; C# 不允许值类型数组变化(同样,它比有符号和无符号类型更通用)。从object 转换时,编译器不能禁止它,因为它根本没有足够的信息来执行此操作,然后 CLR 会成功。

请注意,这只发生在值类型数组中。引用类型数组在 C# 中是变体(不幸的是):

var strs = new string[];
var objs = (object[])strs; //Compiles just fine.

这很不幸,因为它是一个损坏的方差;没有人阻止你这样做:

objs[0] = new object(); //Runtime exception, an object is not a string. Ouch!

另外有趣的是,接口和委托中的 c# 泛型类型差异也不适用于值类型。可以在这里找到为什么会这样的一个很好的解释:here

【讨论】:

  • "您根本无法将值类型拆箱为不是其确切类型的东西。" - 小警告:枚举与整数拆箱在类型之间起作用,只要 基础 类型匹配
  • 枚举在这里是奇怪的鸭子——即使不同枚举类型之间的拆箱也可以,只要它们具有相同的底层类型。 CLR 将枚举视为不同类型的信念有点摇摆不定,真的。
猜你喜欢
  • 2016-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
相关资源
最近更新 更多