web-dev-qa-db-ja.com

C#でパラメーターをGuid.Emptyにデフォルト設定するにはどうすればよいですか?

私は言いたい:

public void Problem(Guid optional = Guid.Empty)
{
}

しかし、コンパイラーは、Guid.Emptyはコンパイル時定数ではないと文句を言います。

APIを変更したくないので、使用できません:

 Nullable<Guid>
167
Ian Ringrose

解決

代わりにnew Guid()を使用できます

public void Problem(Guid optional = new Guid())
{
  // when called without parameters this will be true
  var guidIsEmpty = optional == Guid.Empty;
}

default(Guid)を使用することもできます

default(Guid)new Guid()とまったく同じように機能します。

Guidは参照型ではなく値型であるため、たとえばdefault(Guid)nullと等しくなく、代わりにデフォルトコンストラクターを呼び出すことと同じです。

つまり、これは:

public void Problem(Guid optional = default(Guid))
{
  // when called without parameters this will be true
  var guidIsEmpty = optional == Guid.Empty;
}

元の例とまったく同じです。

説明

Guid.Emptyが機能しなかったのはなぜですか?

エラーが発生する理由は、Emptyが次のように定義されているためです。

public static readonly Guid Empty;

したがって、定数ではなく変数です(constではなくstatic readonlyとして定義されます)。コンパイラーは、メソッドパラメーターのデフォルト値としてのみコンパイラー既知の値を持つことができます(ランタイムのみ既知ではありません)。

根本的な原因は、たとえばconstとは異なり、structenumを使用できないことです。試しても、コンパイルされません。

もう一度理由は、structはプリミティブ型ではないからです。
。NETのすべてのプリミティブタイプのリストについては、 http://msdn.Microsoft.com/en-gb/library/system.typecode.aspx を参照してください。
enumは通常、int(プリミティブ)を継承します)

しかし、new Guid()も定数ではありません!

定数が必要だと言っているのではありません。コンパイル時に決定できるものが必要です。 Emptyはフィールドなので、その値はコンパイル時にはわかりません(実行時の最初のみ)。

デフォルトのパラメーター値は、コンパイル時に認識される必要があります。これは、const値、またはdefault(Guid)new Guid()などのコンパイル時に値を通知するC#機能を使用して定義されたものです。コードではstructコンストラクターを変更できないため、structsのコンパイル時に決定されます)。

defaultまたはnewを簡単に提供できますが、constを提供することはできません(上記で説明したように、プリミティブ型でもenumでもないため)。そのため、オプションのパラメータ自体には定数が必要であると言っているのではなく、コンパイラの既知の値です。

210
Meligy

Guid.Emptynew Guid()と同等で、default(Guid)と同等です。以下を使用できます。

public void Problem(Guid optional = default(Guid))

または

public void Problem(Guid optional = new Guid())

new Foo()値はonlyが次の場合に適用されることに注意してください。

  • あなたは本当にparameterlessコンストラクタを呼び出しています
  • Fooは値型です

言い換えれば、コンパイラがそれが実際に型のデフォルト値に過ぎないことを知っているとき:)

(興味深いことに、99.9%確信していますwont作成したカスタムnew Foo()コンストラクターを呼び出します。C#の値型でそのようなコンストラクターを作成することはできませんが、あなたcan ILでそうします。)

anyタイプにはdefault(Foo)オプションを使用できます。

148
Jon Skeet

使用できません:

default ( Guid )

17
Nick

受け入れられた回答はASP.NET MVCでは機能せず、次のランタイムエラーが発生します。

[ArgumentException: The parameters dictionary contains a null entry for parameter 'optional' of non-nullable type 'System.Guid' for method 'System.Web.Mvc.ActionResult Problem(System.Guid)' ....

代わりに、次のことを実行できます。

public void Problem(Guid? optional)
{
    if (optional == null)
    {
        optional = new Guid();
    }
}
7
Majix

コンパイラは非常に正しいです。 Guid.Emptyはコンパイル時の定数ではありません。次のようなメソッドのオーバーロードを作成してみてください。

public void Problem()
{
    Problem(Guid.Empty);
}
4
a CVn