C#コンパイラは無効な引数エラーをスローします。どうして?

StackOverflow https://stackoverflow.com/questions/270334

  •  06-07-2019
  •  | 
  •  

質問

次のような2つのメソッドを含むクラスがあります:

public String getFoo(Int32 a)
{
  return getBar(a, "b", null);
}

public String getBar(Int32 a, String b, Int32 c)
{
  //do something
  return "";
}

ただし、クラスをコンパイルすると、次の2つのエラーが発生します。

  1. getBar(int、string、int)に最適なオーバーロードメソッドの一致には、無効な引数がいくつかあります
  2. 引数 '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)
{
}

他のヒント

getBarの3番目の引数をNULL可能intにしてみてください。

つまり、署名は次のようになります。

public String getBar(Int32 a, String b, Int32? c)

.NETでnull許容型の詳細を確認できますこちらおよびこちら

Int32は値型です。つまり、nullint?型のパラメーターの有効な引数ではありません。

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));
    

    ちなみに、これは値<=>を渡すのと同じです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top