.net ParameterInfo.IsOptional和ParameterInfo.HasDefaultValue之间的差异?
它们听起来都很相似。从msdn: 获取一个值,该值指示此参数是否为可选参数 此方法依赖于可选的元数据标志。此标志可以是 由编译器插入,但编译器没有义务这样做 此方法使用ParameterAttributes的可选标志 统计员 (在.NET 4.5中新增) 获取一个值,该值指示此参数是否具有默认值 他们不一样吗?我做了快速测试:.net ParameterInfo.IsOptional和ParameterInfo.HasDefaultValue之间的差异?,.net,reflection,default-value,optional-parameters,parameterinfo,.net,Reflection,Default Value,Optional Parameters,Parameterinfo,它们听起来都很相似。从msdn: 获取一个值,该值指示此参数是否为可选参数 此方法依赖于可选的元数据标志。此标志可以是 由编译器插入,但编译器没有义务这样做 此方法使用ParameterAttributes的可选标志 统计员 (在.NET 4.5中新增) 获取一个值,该值指示此参数是否具有默认值 他们不一样吗?我做了快速测试: public void A(string value) { } public void B(string value, int i = -1) { } 我写道:
public void A(string value)
{
}
public void B(string value, int i = -1)
{
}
我写道:
var a = AInfo.GetParameters().Select(p => p.HasDefaultValue).ToArray();
var b = AInfo.GetParameters().Select(p => p.IsOptional).ToArray();
var c = BInfo.GetParameters().Select(p => p.HasDefaultValue).ToArray();
var d = BInfo.GetParameters().Select(p => p.IsOptional).ToArray();
//a equals b; and c equals d
那么,在哪种情况下它们是不同的呢?为什么BCL最近在.NET 4.5中引入了
HasDefaultValue
?使用“a等于b;c等于d”无法得出“它们是相同的”结论,如:
int[]a=new[]{0,1,5};
var c=a.Where(n=>n<2).ToArray();
var d=a.Where(n=>n<3).ToArray();
//你不能说“2==3”,即使c在序列中等于d
好,回到主题,当前一个可选参数总是有一个默认值,这个结论是正确的。但它是未记录的行为,这意味着编译器可能会将其行为/实现更改为可选参数。因此,如果要检查(通过反射)参数是否为可选参数,请使用
.IsOptional
属性。如果要检查它是否具有默认值(可能由某些属性标记,例如DefaultValue?只是可能),请使用.HasDefaultValue
属性。听起来像是多余的词,但这是真的。如果我们看看isonational
的实现,我们会看到:
public bool IsOptional
{
[__DynamicallyInvokable] get
{
return (this.Attributes & ParameterAttributes.Optional) != ParameterAttributes.None;
}
}
它取决于元数据标志,但正如msdn中所述:
此方法依赖于可选的元数据标志。编译器可以插入此标志,但编译器没有义务这样做
这意味着它取决于编译器,如果我们使用其他编译器,我们可以得到具有默认值的参数将不具有IsOptional
标志。
现在让我们看看HasDefaultValue属性是如何实现的:
public override bool HasDefaultValue
{
get
{
if (this.m_noMetadata || this.m_noDefaultValue)
return false;
else
return this.GetDefaultValueInternal(false) != DBNull.Value;
}
}
它总是检查参数是否具有默认值,并且不依赖于编译器。这可能不是100%正确的答案,只是我的想法
更新0
以下示例中,参数没有默认值,但IsOptional
为真:
public static void Method([Optional]string parameter)
{
}
ParameterInfo parameterInfo = typeof(Program).GetMethod("Method").GetParameters()[0];
//Is true
bool isOptional = parameterInfo.IsOptional;
//Is false
bool hasDefaultValue = parameterInfo.HasDefaultValue;
Danny Chen和VVS00205准确地说明了差异,即
IsOptional
始终依赖于编译器,要检查该参数是否是指定默认值的可选参数,请使用hasdaultvalue
bool isOptional = parameterInfo.IsOptional;
bool isOptionalWithADefaultValue = parameterInfo.HasDefaultValue; //.NET 4.5
bool isOptionalWithADefaultValue = (p.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault; //.NET 4 and below
(捕捉一些其他未记录的技术,以在该线程中获得相同的结果)downvoter,如果我的问题很愚蠢,请给出答案,或者留下评论,以便我能以更好的方式提问您是在谈论PropertyInfo(标题)还是ParameterInfo(问题)?@MarcGravell哦,天哪,打败我!我会编辑它的,我明白了,而且我知道它肯定是不能用的(我忽略了它)。这就是为什么我提出这个问题。我刚才说了一个我能想到的场景,
hasdaultvalue
可能不同于isonational
,但事实证明并非如此。社区这样问,因为它听起来像一个基本的2!=3
:)是的,HasDefaultValue
是一种方法,但是在.NET4中,你可以使用p.Attributes&ParameterAttributes。HasDefault
方法ParameterAttributes。HasDefault
也取决于编译器。你说它不是100%正确的意思是什么?答案只是我的想法。你问他们为什么这么做?我不能确切回答他们为什么这样做,所以我只能假设。啊,现在我明白了,但你的措辞并不那么清楚。请找到我的编辑
bool isOptional = parameterInfo.IsOptional;
bool isOptionalWithADefaultValue = parameterInfo.HasDefaultValue; //.NET 4.5
bool isOptionalWithADefaultValue = (p.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault; //.NET 4 and below