3

重複の可能性:
C#: 文字列に null を追加することが合法なのはなぜですか?

有効な C# コードは次のとおりです。

var samsung= "xyz" + null + null + null + null + "890";  // xyz890

これは無効な C# コードです。

var iphone= null.ToString(); // compiler error

最初のステートメントが有効で、2 番目のステートメントが無効である理由と方法は?

4

9 に答える 9

4

+演算子は文字列を連結するためにnull使用され、文字列クラスのインスタンスであるため、演算子の引数として使用できます。"xyz" + null 最終的に文字列「xyz」が返されるため、実際にを追加するまでこのプロセスが繰り返されます"890"

nullはメソッドへの引数の文字列オブジェクトとして使用できますが、メソッド呼び出しを処理するものがないため、実際にメソッドを呼び出すことはできません。

メソッドは、オブジェクトが外部リクエストを処理する方法と考えてください。物事はもう少し意味があります。何を処理するかを引数としてオブジェクトにリクエストを送信することはできますnullが、実際にnull何かを処理するように要求することはできません。

于 2012-11-15T16:06:35.627 に答える
1

+演算子は、次のようなグローバル静的関数と考えることができます。

+(string leftHandSide, string rightHandSide) {
  if (leftHandSide == null)
     leftHandSide = string.Empty;
  if (rightHandSide == null)
     rightHandSide = string.Empty;
  string returnValue;

  // concatenate string

  return returnValue;
}

この文字列連結メソッドは静的であるため、呼び出すインスタンスを必要とせず、null値を処理します。ただし、呼び出しようとするとToStringnullオブジェクトのインスタンスがないToStringため、呼び出す方法がないため、例外が発生します。

于 2012-11-15T16:07:04.753 に答える
1

C# コンパイラは、連結内の null を空の文字列と見なします。

 var samsung= "xyz" + null + null + null + null + "890";

等しい

 var samsung= "xyz" + ""+ ""+ ""+ ""+ "890";

呼び出そnull.toString()うとすると、本質的に null オブジェクトでメソッドを呼び出そうとしています。これは (コンパイルされた場合) 常にNullReferenceException.

于 2012-11-15T15:58:17.347 に答える
1

最初の行では、文字列を連結しています。 nullは何もないので、本質的にあなたは得てxyz890います。それはやっているようなものです1+0+0+0+4が、あなたの秒で、あなたは. 何もないので、呼び出すものは何もありません。初期化されていない変数でメソッドを呼び出そうとしています。ToString()nullnullToString()

于 2012-11-15T15:58:19.163 に答える
1

は参照型であるためstring、 null は暗黙的に に変換できますstring。そして、最初のケースでは、一連の+演算子は次のように変換されますString.Concat(obj1, obj2, obj3, ...)

コードをコンパイルするには、次のように呼び出しますConvert.ToString

var iphone = Convert.ToString(null);
于 2012-11-15T15:59:36.410 に答える
1

これは仕様によるものです。C# 言語仕様を読むことができます。見積もり:

文字列連結:

string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);

+二項演算子のこれらのオーバーロードは、文字列連結を実行します。文字列連結のオペランドが の場合null、空文字列が代入されます。それ以外の場合、文字列以外の引数はToString、 type から継承された仮想メソッドを呼び出すことによって文字列表現に変換されobjectます。ToStringを返す場合null、空の文字列が代用されます。

[...]

したがって、他の人が言っ+たように、2 つの引数を取り、そのうちの 1 つまたは両方が であっても OK である一種のメソッドと考えてnullください。

于 2012-11-15T16:40:53.677 に答える
0

どのような場合でも参照に対してメソッドを呼び出すことはできないnullため、コンパイラはそれを許可しません。 最初のケースでは、コンパイラは文字列定数をプリコンパイルして"xyz890"、正当な代入を行います。

一般に、引数をサポートするコンパイルの+演算子。stringString.Concat(s1, s2, ...)null

2 番目のケースをより正確に言うと、実際の問題はそれが null ポインターであることではなく、メソッドをバインドする型がないことです。他のコメントで指摘されているように、null任意の参照型にキャストでき、問題なくコンパイルできます。

((string)null).ToString();   // compiles, but fails at run-time.
于 2012-11-15T15:58:04.777 に答える
0

+ 演算子は、次のような静的関数に変換されます。

public static string Concat(string first, string second) {...}

関数にパラメーターとして null を渡すことは問題ではありません。それはうまく通過します。その関数は、パラメーターを連結する前に、どちらのパラメーターも null でないことをたまたまチェックします。パラメータのいずれかが null の場合、例外が発生しないように空の文字列として扱われます。ここで重要な点は、この関数によって最初に null チェックされるまで、文字列のインスタンス メンバーが呼び出されないことです。

コンパイル時に評価されるものに対してインスタンス関数をnull.ToString()呼び出すと、例外が発生します。nullこれはまさにそのケースの定義です。

于 2012-11-15T16:04:17.850 に答える
0

IL を見ると、コンパイラが十分にスマートで、null 値を削除して連結文字列を作成するだけであることがわかります。前述のように、null.ToString(); を実行することはできません。string.Empty を実行するか、文字列を null に割り当てることができます。

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] string samsung)
  IL_0000:  nop
  IL_0001:  ldstr      "xyz890"        //null has been removed by compiler.  
  IL_0006:  stloc.0
  IL_0007:  ret
} // end of method Program::Main 

編集
ニールソンのコメントを展開します。null は nil 参照を表すため、文字列 concat の処理方法は、操作などの C# で許可されていると言っても過言ではありません。null値を省略するバイト配列構築を使用しているため、nullを連結しているように見えるだけだと思います。

于 2012-11-15T16:04:37.133 に答える