質問
次のような2つのメソッドを含むクラスがあります:
public String getFoo(Int32 a)
{
return getBar(a, "b", null);
}
public String getBar(Int32 a, String b, Int32 c)
{
//do something
return "";
}
ただし、クラスをコンパイルすると、次の2つのエラーが発生します。
- getBar(int、string、int)に最適なオーバーロードメソッドの一致には、無効な引数がいくつかあります
- 引数 '3': '
<null>
'から 'int'に変換できません
このエラーが発生する理由は理解できたと思います。コンパイラは知らない コンパイル時に、オブジェクトの実際のタイプが何であるか。 エラーの原因について私が正しいかどうかを確認したり、本当の理由を指摘したりできますか?
さらに重要なことは、この方法でコードを設計できますか?その場合、エラーを修正するには何をする必要がありますか?クラスをこのように設計する理由は、getBar、getFooのコードを複製したくないためです。 2つのメソッドは、3番目のパラメーターを受け取ることを除いて、本質的に同じことを行います。
ありがとう。
解決
.NETには、参照型と値型の間に明確な概念があります。
参照型は、ヒープに割り当てられるオブジェクトです(System.Objectのサブクラスになります)。スタック上にあるのは、このオブジェクトへのポインタだけです。そのため、nullポインターを格納することは完全に有効です。
値型は、スタックに割り当てられるオブジェクトであり、System.ValueTypeのサブクラスになります。値型はスタック上に存在するため、その値を関数に渡すと、オブジェクトのコンテンツ全体が渡されます。
値の型はnullにできません。
ほとんどのC#プリミティブ型は値型です。文字列は、実際には参照型である特別な種類のプリミティブです。
.NET 2.0では、MSは構造体内にジェネリック型を囲む機能を追加して、null許容型をシミュレートできるようにしました。実際に起こるのは、Nullable <!> lt; T <!> gt;内のロジックです。 structはnullをエミュレートしています。
彼らは、タイプに疑問符を追加することにより、構文のショートカットを使用してそれを表現しました:
int? nullableInt = null;
float? nullableFloat = null;
etc ...
intが気に入らない場合は?構文では、常にNullable <!> lt; SomeType <!> gt;
を使用できますpublic String getBar(Int32 a, String b, Nullable<Int32> c)
補足として、構文をより良くするために、あなたがやっていることを行うときにオーバーロードを追加することを好みます。
public String getBar(Int32 a, String b)
{
this.getBar(a,b,null);
}
public String getBar(Int32 a, String b, Nullable<Int32> c)
{
}
他のヒント
Int32
は値型です。つまり、null
はint?
型のパラメーターの有効な引数ではありません。
null許容の整数が本当に必要な場合は、<=>タイプを使用します。
表示されている2つのエラーは、実際には同じエラーです。
晴れです。
Int32は値型であり、値「null」を保持できません。パラメーター値として「null」を渡す必要がある場合は、引数タイプとしてInt32ではなくNullableを使用します。
Nullable Types(C#プログラミングガイド) MSDNで。
Int32は、値/ nullを許可しない型であるintのエイリアスです。 null可能バージョンの場合は、System.Nullableまたは単に「int?」を使用します。
また、null不可のintに戻すことを忘れないでください:
int? nullable = ...;
int non_nullable = nullable??0;
数値は、実際にnullである場合に想定される値を示します。
Int32はnullにできません。代わりに、null許容型にします:
public String getBar(Int32 a, String b, Int32? c)
{
if (c.HasValue)
{
...do something with c.Value...
}
return "";
}
OK、それで five 7人がint?
を解決策として提案しました。状況に応じて、より適切な 解決策を2つ提案します。
-
引数が2つしかないメソッドのオーバーロードを作成し、呼び出し時に
null
を省略します:public String getFoo(Int32 a) { return getBar(a, "b", null); } public String getBar(Int32 a, String b) { //do something else, without the int }
コードの重複を避けたいと述べたので、おそらくこれはしたくないでしょう。
-
default
の代わりに0
を使用:return getBar(a, "b", default(int));
ちなみに、これは値<=>を渡すのと同じです。