133

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

var bob = "abc" + null + null + null + "123";  // abc123

これは有効な C# コードではありません

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

最初のステートメントが有効なのはなぜですか?

4

11 に答える 11

166

最初のものが機能する理由:

MSDNから:

文字列連結操作では、C# コンパイラは null 文字列を空の文字列と同じように扱いますが、元の null 文字列の値は変換しません。

+ 二項演算子の詳細:

2 項 + 演算子は、一方または両方のオペランドが文字列型の場合に文字列連結を実行します。

文字列連結のオペランドが null の場合、空の文字列が代入されます。それ以外の場合、ToString型 object から継承された仮想メソッドを呼び出すことにより、文字列以外の引数は文字列表現に変換されます。

ToStringを返す場合null、空の文字列が代用されます。

秒単位のエラーの理由は次のとおりです。

null (C# リファレンス) - null キーワードは、オブジェクトを参照しない null 参照を表すリテラルです。null は参照型変数のデフォルト値です。

于 2012-05-30T10:19:02.970 に答える
109

C#の演算子は、静的メソッドである に+内部的に変換されるためです。そして、このメソッドはたまたま空の文字列のようString.Concatに扱われます。Reflectornullのソースを見ると、次のように表示されます。String.Concat

// while looping through the parameters
strArray[i] = (str == null) ? Empty : str;
// then concatenate that string array

(MSDN でも言及されています: http://msdn.microsoft.com/en-us/library/k9c94ey1.aspx )

一方、ToString()は呼び出すことができないインスタンス メソッドですnull(どの型を使用する必要がありnullますか?)。

于 2012-05-30T10:17:32.157 に答える
30

最初のサンプルは次のように翻訳されます。

var bob = String.Concat("abc123", null, null, null, "abs123");

このConcatメソッドは入力をチェックし、null を空の文字列として変換します

2番目のサンプルは次のように変換されます。

var wtf = ((object)null).ToString();

したがって、nullここで参照例外が生成されます

于 2012-05-30T10:19:43.743 に答える
11

コードの最初の部分は、のように扱われますString.Concat

これは、文字列を追加するときにC#コンパイラが呼び出すものです。"abc" + nullに翻訳されますString.Concat("abc", null)

内部的には、そのメソッドは。に置き換えnullられString.Emptyます。したがって、コードの最初の部分で例外がスローされないのはそのためです。まるで

var bob = "abc" + string.Empty + string.Empty + string.Empty + "123";  //abc123

また、コードの2番目の部分では、「null」はオブジェクトではないため、例外がスローされます。nullキーワードは、オブジェクトを参照しないnull参照を表すリテラルです。nullは、参照型変数のデフォルト値です。

また、' ToString()'はオブジェクトのインスタンスから呼び出すことができるメソッドですが、リテラルは呼び出すことができません。

于 2012-05-30T10:28:46.477 に答える
9

.net より前の COM フレームワークでは、文字列を受け取ったルーチンは、処理が終わったときに文字列を解放する必要がありました。空文字列がルーチンに出入りすることは非常に一般的であり、null ポインターを「解放」しようとすることは正当な何もしない操作として定義されていたため、Microsoft は null 文字列ポインターが空の文字列を表すようにすることにしました。

COM との互換性を確保するために、.net の多くのルーチンは、null オブジェクトを有効な表現として空の文字列として解釈します。.net とその言語のいくつかのわずかな変更 (最も注目すべきは、インスタンス メンバーが「仮想として呼び出さない」ことを示すことができるようにすること) により、Microsoft はnull、宣言された型 String のオブジェクトを空の文字列のように動作させることができました。Microsoftがそれを行った場合、Nullable<T>動作を多少異なるものにする必要があったでしょう(許可するために、Nullable<String>とにかく私見がすべきことを許可するため)、および/またはNullableStringとほとんど交換可能でStringあるが、を考慮しない型を定義する必要がありましたnull有効な空の文字列として。

そのままでは、nulla が正当な空の文字列と見なされるコンテキストとそうでないコンテキストがあります。それほど役立つ状況ではありませんが、プログラマーは知っておくべき状況です。一般に、isのstringValue.someMember場合、フォームの式は失敗しますが、パラメーターとして文字列を受け入れるほとんどのフレームワーク メソッドと演算子は、空の文字列と見なされます。stringValuenullnull

于 2012-05-30T14:39:59.890 に答える
5

'+'中置演算子です。他の演算子と同様に、実際にはメソッドを呼び出しています。非中置バージョンを想像できます"wow".Plus(null) == "wow"

実装者はこのようなことを決定しました...

class String
{
  ...
  String Plus(ending)
  {
     if(ending == null) return this;
     ...
  }
} 

だから..あなたの例は

var bob = "abc".Plus(null).Plus(null).Plus(null).Plus("123");  // abc123

これはと同じです

var bob = "abc".Plus("123");  // abc123

null が文字列になることはありません。それnull.ToString()も同じです null.VoteMyAnswer()。;)

于 2012-05-31T12:19:23.817 に答える
3

このディスカッション スレッドで、何もないところから文字列を作成することはできないと誰かが言いました。 (私が思うに、これは素晴らしいフレーズです)。ただし、次の例に示すように、できます:-)。

var x = null + (string)null;     
var wtf = x.ToString();

正常に動作し、例外をまったくスローしません。唯一の違いは、null の 1 つを文字列にキャストする必要があることです。(文字列)キャストを削除しても、例はコンパイルされますが、実行時例外がスローされます。タイプ '<null>' および '<null>'".

: 上記のコード例では、x の値は予想どおり null ではありません。実際には、オペランドの 1 つを文字列にキャストした後の空の文字列です。


もう 1 つの興味深い事実は、C# / .NET では、データ型が異なると処理方法nullが必ずしも同じではないということです。例えば:

int? x = 1;  //  string x = "1";
x = x + null + null;
Console.WriteLine((x==null) ? "<null>" : x.ToString());

コード スニペットの1 行目を見てください。が値を含むxnull 許容整数変数 (つまり) である場合、結果が返されます。それが value の文字列 (コメントに示されているように) である場合、 .ではなく返されます。int?1<null>"1""1"<null>

: またvar x = 1;、最初の行で使用している場合は、実行時エラーが発生します。なんで?割り当てにより、変数が null 許容ではないxdatatypeに変換されるためです。intコンパイラはここで想定していないため、が追加さint?れた 2 行目で失敗します。null

于 2012-06-19T12:49:22.620 に答える
3

オブジェクトを参照しないリテラルだからだと思います。ToString()が必要objectです。

于 2012-05-30T10:18:21.960 に答える
2

文字列への追加nullは単純に無視されます。null(2番目の例では)オブジェクトのインスタンスではないため、ToString()メソッドさえありません。それはただの文字通りです。

于 2012-05-30T10:20:01.553 に答える
1

文字列を連結するときとの間string.Emptyに違いはないからです。nullnull を渡すこともできますstring.Format。しかし、 でメソッドを呼び出そうとすると、null常に がNullReferenceException発生するため、コンパイラ エラーが発生します。
何らかの理由で本当にやりたい場合は、 をチェックしnullてから返す拡張メソッドを書くことができますstring.Empty。しかし、そのような拡張機能は、絶対に必要な場合にのみ使用する必要があります (私の意見では)。

于 2012-05-30T10:21:09.210 に答える
0

一般的に: 仕様に応じて、パラメーターとして null を受け入れることが有効である場合とそうでない場合がありますが、null でメソッドを呼び出すことは常に無効です。


それが、文字列の場合に + 演算子のオペランドが null になる可能性がある理由です。これは、プログラマーの生活を楽にするための、またはプログラマーが null を処理できないと仮定するための、ちょっとした VB のことです (ごめんなさい)。私はこの仕様に完全に同意しません。'unknown' + 'anything' はまだ 'unknown' である必要があります...

于 2015-10-31T07:59:25.013 に答える