首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ParameterInfo.IsOptional与ParameterInfo.HasDefaultValue的差异?

ParameterInfo.IsOptional与ParameterInfo.HasDefaultValue的差异?
EN

Stack Overflow用户
提问于 2013-04-24 08:06:23
回答 3查看 1.3K关注 0票数 14

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

ParameterInfo.IsOptional

获取一个值,该值指示此参数是否为可选参数。 此方法依赖于可选元数据标志。编译器可以插入此标志,但编译器不必这样做。 此方法利用ParameterAttributes枚举数的可选标志。

ParameterInfo.HasDefaultValue (在.NET 4.5中新增)

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

它们不是一样的吗?我做了快速测试:

代码语言:javascript
运行
复制
public void A(string value)
{

}
public void B(string value, int i = -1)
{

}

我写道:

代码语言:javascript
运行
复制
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在新的HasDefaultValue 4.5中引入.NET?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-24 09:03:20

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

代码语言:javascript
运行
复制
public bool IsOptional
{
  [__DynamicallyInvokable] get
  {
    return (this.Attributes & ParameterAttributes.Optional) != ParameterAttributes.None;
  }
}

它依赖于元数据标志,但它是在msdn中编写的:

此方法依赖于可选元数据标志。编译器可以插入此标志,但编译器不必这样做。

这意味着它取决于编译器,如果我们使用其他编译器,则可以获得具有默认值的参数将不具有IsOptional标志。现在让我们看看HasDefaultValue属性是如何实现的:

代码语言:javascript
运行
复制
public override bool HasDefaultValue
{
  get
  {
    if (this.m_noMetadata || this.m_noDefaultValue)
      return false;
    else
      return this.GetDefaultValueInternal(false) != DBNull.Value;
  }
}

它总是检查参数是否具有默认值,并且不依赖于编译器。这可能不是百分之百正确的答案,只是我的想法。

更新0

下面是一个示例,其中参数没有默认值,但IsOptional是真的:

代码语言:javascript
运行
复制
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;
票数 7
EN

Stack Overflow用户

发布于 2013-04-24 10:58:12

Danny和vvs0205准确地说明了不同之处,即IsOptional总是依赖于编译器,并检查参数是否是一个可选参数,其默认值是指定的,使用HasDefaultValue

代码语言:javascript
运行
复制
bool isOptional = parameterInfo.IsOptional;

bool isOptionalWithADefaultValue = parameterInfo.HasDefaultValue; //.NET 4.5

bool isOptionalWithADefaultValue = (p.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault; //.NET 4 and below

从这里取走 (捕获其他一些无文档的技术来获得线程中的相同信息)

票数 3
EN

Stack Overflow用户

发布于 2013-04-24 08:32:47

使用"a等于b;c等于d“不能得出”它们是相同的“的结论,例如:

代码语言:javascript
运行
复制
int[] a = new[] { 0, 1, 5 };
var c = a.Where(n => n < 2).ToArray();
var d = a.Where(n => n < 3).ToArray();  
//you can't say "2 == 3" even c equals to d in sequence

好,回到主题,当前一个可选参数总是有一个默认值,这个结论是正确的。但是AFAIK它是无文档的行为,这意味着编译器可能将其行为/实现更改为可选参数。因此,如果要检查(通过反射)参数是否为可选参数,请使用.IsOptional属性。如果您想要检查它是否有默认值(可能由某些属性标记,例如DefaultValue )?使用.HasDefaultValue属性。听起来像是多余的话,但这是真的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16186694

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档