.NET获取自定义值类型可选参数默认值返回null问题咨询
这是不是.NET的bug?
不是,这是CLR反射API的设计行为。
当你为值类型可选参数指定default作为默认值时,CLR会将其解析为该值类型的零初始化状态(所有字段设为对应类型的默认值,比如Bar的Value字段为null)。但通过ParameterInfo.DefaultValue或RawDefaultValue获取时,会返回null——这是反射API的特殊标记,用来表示“该参数的默认值是其类型的CLR默认值”,而非实际的装箱后值类型实例。
需要注意的是:你定义的Bar结构体显式实现了无参构造函数,这会生成一个自定义实例(Value为"default constructor"),但可选参数的default和显式构造函数无关,它始终对应CLR自动生成的零初始化状态。
如何正确获取默认值?
你的代码思路是正确的,paramInfo.HasDefaultValue && paramInfo.ParameterType.IsValueType && paramInfo.DefaultValue == null这个判断逻辑可以覆盖所有需要手动生成类型默认值的场景:
- 当参数是值类型、标记了有默认值但反射返回
null时,说明需要获取该类型的CLR零初始化实例; - 其他场景(引用类型、值类型但反射能返回具体值,比如
int的0)直接返回DefaultValue即可。
优化后的实现代码如下:
public static object? GetDefaultParameterValue(ParameterInfo paramInfo) { if (!paramInfo.HasDefaultValue) { return GetDefaultValueOfType(paramInfo.ParameterType); } var defaultValue = paramInfo.DefaultValue; // 值类型但反射返回null,说明是CLR默认零初始化状态 if (paramInfo.ParameterType.IsValueType && defaultValue == null) { return GetDefaultValueOfType(paramInfo.ParameterType); } return defaultValue; } public static object? GetDefaultValueOfType(Type type) { if (!type.IsValueType) return null; return typeof(DefaultValueGenerator) .GetMethod(nameof(DefaultValueGenerator.GetDefault)) .MakeGenericMethod(type) .Invoke(null, null); } private static class DefaultValueGenerator { public static T GetDefault<T>() => default; }
调用这个方法获取barVal的默认值时,会得到Bar的零初始化实例,调用其ToString()方法会输出你预期的Bar [value is null]。
另外需要注意:Activator.CreateInstance(typeof(Bar))会调用结构体的显式无参构造函数,得到的是自定义初始化的实例,和可选参数default对应的CLR零初始化状态完全不同,因此不适用此场景。
内容的提问来源于stack exchange,提问作者hypehuman

