Reflection: Allow ParameterBuilder.SetConstant(nonNullValue) for nullable enum parame...
authorstakx <stakx@eml.cc>
Mon, 14 May 2018 14:20:53 +0000 (16:20 +0200)
committerAtsushi Kanamori <AtsushiKan@users.noreply.github.com>
Mon, 14 May 2018 14:20:53 +0000 (07:20 -0700)
* ParameterBuilder.SetConstant(nonNull) for TEnum?

This change makes it possible to use `ParameterBuilder.SetConstant`
to set a non-null default value for parameters having a nullable enum
type.

* ParameterInfo.DefaultValue for TEnum?

Add a note to `MdConstant.GetValue` (which sits behind `ParameterInfo.
[Raw]DefaultValue`) explaining why changing its behavior to mirror the
change in `TypeBuilder.SetConstantValue` would be a breaking change.

Commit migrated from https://github.com/dotnet/coreclr/commit/f1c47fa7d2cdf29c5d0d1d7c89855e0d0ee5518a

src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/MdConstant.cs

index f517decc1d8a2ec72aae5bfee8fa29f50a03b94f..7fc7132f40605d4ff7349f9d2302467e456cf819 100644 (file)
@@ -301,6 +301,10 @@ namespace System.Reflection.Emit
                 if (destType.IsByRef)
                     destType = destType.GetElementType();
 
+                // Convert nullable types to their underlying type.
+                // This is necessary for nullable enum types to pass the IsEnum check that's coming next.
+                destType = Nullable.GetUnderlyingType(destType) ?? destType;
+
                 if (destType.IsEnum)
                 {
                     //                                   |  UnderlyingSystemType     |  Enum.GetUnderlyingType() |  IsEnum
index 5284bcae0b1d2001969b44c84c8ec5e173054e7d..e7e0684785f8b2bc189db584e7954eac717692f8 100644 (file)
@@ -23,6 +23,12 @@ namespace System.Reflection
 
             if (fieldType.IsEnum && raw == false)
             {
+                // NOTE: Unlike in `TypeBuilder.SetConstantValue`, if `fieldType` describes
+                // a nullable enum type `Nullable<TEnum>`, we do not unpack it to `TEnum` to
+                // successfully enter this `if` clause. Default values of `TEnum?`-typed
+                // parameters have been reported as values of the underlying type, changing
+                // this now might be a breaking change.
+
                 long defaultValue = 0;
 
                 switch (corElementType)