public enum Foo { X, Y };
[...]
public Foo Bar { set { ... } }
[...]
PropertyInfo prop = obj.GetType().GetProperty("Bar");
prop.SetValue(obj, (object)1, null);
I.e. you can use reflection to set the value of a property of an enum type using its integer value. (You could also just cast it like so: obj.Bar = (Foo)1;, but that's not quite as interesting, for reasons that will be revealed later.)
Also, a boxed value and a boxed nullable value have the same representation, right? They are both pointers to a small object containing the primitive. As the following code shows, boxed integers and boxed nullable integers are interchangeable:
int intValue = 1;
int? nullableIntValue = 1;
object boxedInt = intValue;
object boxedNullableInt = nullableIntValue;
intValue = (int)boxedNullableInt;
nullableIntValue = (int?)boxedInt;
And, not surprisingly, the same holds for enum values, now demonstrated using reflection as in our first example:
public Foo? Bar { set { ... } }
[...]
prop.SetValue(obj, (object)Foo.X, null);
Now, combining these two examples, what do you think the following code would do?
public Foo? Bar { set { ... } }
[...]
prop.SetValue(obj, (object)1, null);
If you, like me, thought it would happily set the property to the enum value correspoding to 1, in this case Foo.X, you'd be wrong. Instead it throws the following exception:
Object of type 'System.Int32' cannot be converted to type 'System.Nullable`1
Huh? The .net designers may know why this is, and they may even have a good reason for it, but to me it just seems plain weird. It is worth noting that obj.Bar = (Foo?)1; works just fine.
This issue came up when mapping objects from database tables, using integers to represent enum values. I've reluctantly added the following workaround to my mapping code:
PropertyInfo prop = [...]
object val = [...]
if ((prop.PropertyType.IsGenericType) &&
(prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
Type targetType = prop.PropertyType.GetGenericArguments()[0];
if (targetType.IsEnum)
val = Enum.ToObject(targetType, val);
}
prop.SetValue(obj, val, null);