Not much to say,
This is the issue:
public static T WriteIfNotNull<T>(ManagementObject retObject, string parameter)
{
return retObject[parameter] != null ? (T)retObject[parameter] : default(T);
}
It breaks when T is an int and retObject[parameter] is an object. The odd part (for me at least) is that if T is not T and is actually a specified int it does work.
It says it can’t be casted to T (even that in this case T is int).
@Edit: @dtb here it goes:
Specified cast is not valid.
(T)(object)retObject[parameter] Cannot unbox 'retObject[parameter]' as a 'T' int
And the values:
parameter: "ProcessId"
retObject[parameter]: 4
default(T): 0
@@Edit: Here’s the call too
pr.ProcessId = Util.WriteIfNotNull<int>(retObject, "ProcessId");
It seems to me that what’s happening is that
retObject[parameter]isn’t actually anintbut is another numeric type (uintfor process IDs typically), in which case you’d want to useConvertto actually change the value:The reason a simple cast doesn’t work here is because casting from
objecttointonly works if it’s actually a boxedint. You can’t do a downcast and conversion cast in one operation because there is not a conversion cast fromobjecttoint. Thus casting away fromobjectrequires you to cast to the exact type or a valid super-type, interface, etc of the exact type.So, to convert a boxed
uintto anintwe’d have to either unbox as anintfirst (problematic) or use one of theConvertmethods to change the type (as shown above).Convert.ChangeType()works for converting between compatible types even if they are boxed. For example, ifretObject[parameter]returns alongthen this will allow it to be converted to aTofint.I have a blog post on this here with more detail, hopefully this makes sense. The gist, again, is that casting from
objectis a downcast (no conversion casts are defined forobject) thus you must cast it to it’s precise type (or a valid sub-type).