为什么可以';我不能从系统中提取一个ushort对象,然后将其转换为uint吗?(C#)

为什么可以';我不能从系统中提取一个ushort对象,然后将其转换为uint吗?(C#),c#,casting,strong-typing,C#,Casting,Strong Typing,我正在处理列表中的项目,该列表是System.Management.ManagementObjectCollection。这些项中的每一项都是一个System.Management.ManagementObject,其中包含按字符串索引的属性。见: foreach (ManagementObject queryObj in searcher.Get()) { string osversion = (string)queryObj["Version"]; string os = (

我正在处理列表中的项目,该列表是
System.Management.ManagementObjectCollection
。这些项中的每一项都是一个
System.Management.ManagementObject
,其中包含按字符串索引的属性。见:

foreach (ManagementObject queryObj in searcher.Get())
{
    string osversion = (string)queryObj["Version"];
    string os = (string)queryObj["Name"];
    uint spmajor = (uint)queryObj["ServicePackMajorVersion"];
    uint spminor = (uint)queryObj["ServicePackMinorVersion"];
    ...
    ...
    ...
}
queryObj
的每次“字典访问”都会返回一个C#
对象
,它实际上是属性应该是什么——我必须事先知道它们的“真实”类型,这没关系

问题是,我在
uint
强制转换中得到了一个
InvalidCastException
。我必须使用实类型,即
ushort
。从
ushort
uint
的转换不应该被接受和明显吗


在本例中,我最终会将值转换为
string
,但如果我必须将它们转换为
uint
int
long
变量,该怎么办?

您正试图取消装箱一个ushort,而它只能取消装箱到一个ushort

一旦你解开了它,你就可以把它当作普通的

类型为T的任何装箱值只能解除装箱到T(或可为null的值)


Eric Lippert就这件事发表了一篇非常好的博客文章。

casting操作符的问题是它实际上意味着两件事:cast和convert。可以将数值从一个数字转换为另一个数字,但不能将装箱的数字转换为错误的数字类型。因此,您需要做的是:

uint spmajor = (uint)(ushort)queryObj["ServicePackMajorVersion"];
更好的是:

uint spmajor = Convert.ToUInt32(queryObj["ServicePackMajorVersion"]);

事实上,这也有一些例外。我能立即记住的一点是,可以将具有底层“int”类型的枚举取消装箱为int,反之亦然。当我第一次看到这一点时,我感到非常惊讶。哈哈,是的,这听起来确实令人惊讶:-)另外,Eric提到了这条规则的另一个例外是,可以将其强制转换为null。Jon,我可能在这里表示缺乏理解,但枚举是否会被装箱?如果它们没有,我会说它们没有违反这条规则,因为它只适用于装箱类型。它们是值类型,所以它们会装箱。@DoctaJonez:是的,枚举会装箱,因为它们是值类型