views:

288

answers:

2

I'm manipulating the items in a list that's a System.Management.ManagementObjectCollection. Each of these items is a System.Management.ManagementObject which contains properties indexed by string. See:

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"];
    ...
    ...
    ...
}

Each "dictionary access" to queryObj returns a C# object which is in fact whatever the property is supposed to be -- I have to know their "real" type beforehand, and that's OK.

Problem is, I get a InvalidCastException in the uint casts. I have to use the real type, which is ushort. Shouldn't a cast from ushort to uint be acceptable and obvious?

In this case, I'll eventually convert the values to string, but what if I had to get them into uint or int or long variables?

+15  A: 

You're attempting to unbox a ushort, and it can only be unboxed to a ushort.

Once you've unboxed it you can then cast it as normal.

Any boxed value of type T can only be unboxed to a T (or a Nullable).

Eric Lippert did a very good blog post about this exact thing here.

DoctaJonez
There are some exceptions to this, actually. The one I can remember immediately is that you can unbox an enum with an underlying "int" type to int, and vice versa. I was most surprised when I first saw that.
Jon Skeet
Haha, yeah that does sound surprising :-) Also, Eric mentioned another exception to this rule is that you can cast to a Nullable.
DoctaJonez
Jon, I'm probably demonstrating a lack of understanding here, but do Enums get boxed? If they don't then I'd say they don't contravene this rule, because it only applies to boxed types.
DoctaJonez
They are value types, so they do get boxed.
Groo
@ DoctaJonez : yes, Enums get boxed, since they are value types
Thomas Levesque
It's always good to find these things out ;-) In that case I'm surprised that Enums violate this behaviour for boxed types.
DoctaJonez
@Skeet: one could argue that an enum "is" its underlying integer type more strongly than an integer "is" another integer of different width. Well, what do you know, you CAN argue what "is" is!
JCCyC
+2  A: 

The problem with the casting operator is it really means two things: cast and convert. You can convert a value from a number to a different number, but you cannot cast a boxed number to the wrong type of number. Thus, what you'd have to do instead is:

uint spmajor = (uint)(ushort)queryObj["ServicePackMajorVersion"];

Better yet:

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