14

どちらも同じように聞こえます。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

では、それらはどのような文脈で異なるのでしょうか? BCLHasDefaultValueが .NET 4.5 で新たに導入されたのはなぜですか?

4

3 に答える 3

7

の実装を見ると、次の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;
于 2013-04-24T09:03:20.093 に答える
3

Danny Chen と vvs0205 は違いを正確に述べています。これは常にコンパイラに依存し、パラメーターがデフォルト値が指定されIsOptionalているオプションのパラメーターであるかどうかを確認するには、use を使用します。HasDefaultValue

bool isOptional = parameterInfo.IsOptional;

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

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

hereから取得しました(他の文書化されていない手法をキャッチして、そのスレッドで同じものを取得します

于 2013-04-24T10:58:12.707 に答える
1

次のように、「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();  
//you can't say "2 == 3" even c equals to d in sequence

トピックに戻ると、現在、オプションのパラメーターには常にデフォルト値があり、この結論は「今のところ」正しいです。しかし、知る限り、これは文書化されていない動作です。つまり、コンパイラはその動作/実装をオプションのパラメーターに変更する可能性があります。したがって、パラメーターがオプションのパラメーターであるかどうかを (リフレクションを介して) チェックしたい場合は、.IsOptionalプロパティを使用します。デフォルト値があるかどうかを確認したい場合(おそらく、DefaultValueなどの属性でマークされている可能性がありますか?)、.HasDefaultValueプロパティを使用します。余計な言葉に聞こえますが本当です。

于 2013-04-24T08:32:47.523 に答える