簡體   English   中英

ParameterInfo.IsOptional和ParameterInfo.HasDefaultValue之間的區別?

[英]Difference between ParameterInfo.IsOptional and ParameterInfo.HasDefaultValue?

它們聽起來都很相似。 來自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;

Danny Chen和vvs0205准確地說明了差異, IsOptional總是依賴於編譯器,並檢查參數是否是指定默認值的可選參數使用HasDefaultValue

bool isOptional = parameterInfo.IsOptional;

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

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

從這里采取捕獲一些其他未記錄的技術,以在該線程中獲得相同

使用“a equals 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();  
//you can't say "2 == 3" even c equals to d in sequence

好的回到主題, 目前可選參數總是有一個默認值,這個結論“現在”是正確的。 但是AFAIK它的未記錄行為,這意味着編譯器可能會將其行為/實現更改為可選參數。 因此,如果要檢查(通過反射)參數是否為可選參數,請使用.IsOptional屬性。 如果要檢查它是否具有默認值(可能標記為某個屬性,例如DefaultValue?只是可能),請使用.HasDefaultValue屬性。 聽起來像多余的話,但這是真的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM