私は言いたい:
public void Problem(Guid optional = Guid.Empty)
{
}
しかし、コンパイラーは、Guid.Emptyはコンパイル時定数ではないと文句を言います。
APIを変更したくないので、使用できません:
Nullable<Guid>
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
とは異なり、struct
のenum
を使用できないことです。試しても、コンパイルされません。
もう一度理由は、struct
はプリミティブ型ではないからです。
。NETのすべてのプリミティブタイプのリストについては、 http://msdn.Microsoft.com/en-gb/library/system.typecode.aspx を参照してください。
(enum
は通常、int
(プリミティブ)を継承します)
new Guid()
も定数ではありません!定数が必要だと言っているのではありません。コンパイル時に決定できるものが必要です。 Empty
はフィールドなので、その値はコンパイル時にはわかりません(実行時の最初のみ)。
デフォルトのパラメーター値は、コンパイル時に認識される必要があります。これは、const
値、またはdefault(Guid)
やnew Guid()
などのコンパイル時に値を通知するC#機能を使用して定義されたものです。コードではstruct
コンストラクターを変更できないため、struct
sのコンパイル時に決定されます)。
default
またはnew
を簡単に提供できますが、const
を提供することはできません(上記で説明したように、プリミティブ型でもenum
でもないため)。そのため、オプションのパラメータ自体には定数が必要であると言っているのではなく、コンパイラの既知の値です。
Guid.Empty
はnew Guid()
と同等で、default(Guid)
と同等です。以下を使用できます。
public void Problem(Guid optional = default(Guid))
または
public void Problem(Guid optional = new Guid())
new Foo()
値はonlyが次の場合に適用されることに注意してください。
Foo
は値型です言い換えれば、コンパイラがそれが実際に型のデフォルト値に過ぎないことを知っているとき:)
(興味深いことに、99.9%確信していますwont作成したカスタムnew Foo()
コンストラクターを呼び出します。C#の値型でそのようなコンストラクターを作成することはできませんが、あなたcan ILでそうします。)
anyタイプにはdefault(Foo)
オプションを使用できます。
使用できません:
default ( Guid )
?
受け入れられた回答は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();
}
}
コンパイラは非常に正しいです。 Guid.Empty
はコンパイル時の定数ではありません。次のようなメソッドのオーバーロードを作成してみてください。
public void Problem()
{
Problem(Guid.Empty);
}