他们听起来都很相似。来自msdn:

ParameterInfo.IsOptional


获取一个值,该值指示此参数是否可选。

此方法取决于可选的元数据标志。该标志可以是
由编译器插入,但编译器没有义务这样做。

此方法利用ParameterAttributes的Optional标志
枚举器。


ParameterInfo.HasDefaultValue(。NET 4.5中的新功能)


获取一个值,该值指示此参数是否具有默认值。


他们不一样吗?我做了快速测试:

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

最佳答案

如果我们看一下IsOptional的实现,我们将看到:

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为true的示例:

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;

08-26 23:56