これは有効な C# コードです
var bob = "abc" + null + null + null + "123"; // abc123
これは有効な C# コードではありません
var wtf = null.ToString(); // compiler error
最初のステートメントが有効なのはなぜですか?
最初のものが機能する理由:
MSDNから:
文字列連結操作では、C# コンパイラは null 文字列を空の文字列と同じように扱いますが、元の null 文字列の値は変換しません。
+ 二項演算子の詳細:
2 項 + 演算子は、一方または両方のオペランドが文字列型の場合に文字列連結を実行します。
文字列連結のオペランドが null の場合、空の文字列が代入されます。それ以外の場合、
ToString
型 object から継承された仮想メソッドを呼び出すことにより、文字列以外の引数は文字列表現に変換されます。
ToString
を返す場合null
、空の文字列が代用されます。
秒単位のエラーの理由は次のとおりです。
null (C# リファレンス) - null キーワードは、オブジェクトを参照しない null 参照を表すリテラルです。null は参照型変数のデフォルト値です。
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
ますか?)。
最初のサンプルは次のように翻訳されます。
var bob = String.Concat("abc123", null, null, null, "abs123");
このConcat
メソッドは入力をチェックし、null を空の文字列として変換します
2番目のサンプルは次のように変換されます。
var wtf = ((object)null).ToString();
したがって、null
ここで参照例外が生成されます
コードの最初の部分は、のように扱われます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()
'はオブジェクトのインスタンスから呼び出すことができるメソッドですが、リテラルは呼び出すことができません。
.net より前の COM フレームワークでは、文字列を受け取ったルーチンは、処理が終わったときに文字列を解放する必要がありました。空文字列がルーチンに出入りすることは非常に一般的であり、null ポインターを「解放」しようとすることは正当な何もしない操作として定義されていたため、Microsoft は null 文字列ポインターが空の文字列を表すようにすることにしました。
COM との互換性を確保するために、.net の多くのルーチンは、null オブジェクトを有効な表現として空の文字列として解釈します。.net とその言語のいくつかのわずかな変更 (最も注目すべきは、インスタンス メンバーが「仮想として呼び出さない」ことを示すことができるようにすること) により、Microsoft はnull
、宣言された型 String のオブジェクトを空の文字列のように動作させることができました。Microsoftがそれを行った場合、Nullable<T>
動作を多少異なるものにする必要があったでしょう(許可するために、Nullable<String>
とにかく私見がすべきことを許可するため)、および/またはNullableString
とほとんど交換可能でString
あるが、を考慮しない型を定義する必要がありましたnull
有効な空の文字列として。
そのままでは、null
a が正当な空の文字列と見なされるコンテキストとそうでないコンテキストがあります。それほど役立つ状況ではありませんが、プログラマーは知っておくべき状況です。一般に、isのstringValue.someMember
場合、フォームの式は失敗しますが、パラメーターとして文字列を受け入れるほとんどのフレームワーク メソッドと演算子は、空の文字列と見なされます。stringValue
null
null
'+'
中置演算子です。他の演算子と同様に、実際にはメソッドを呼び出しています。非中置バージョンを想像できます"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()
。;)
このディスカッション スレッドで、何もないところから文字列を作成することはできないと誰かが言いました。 (私が思うに、これは素晴らしいフレーズです)。ただし、次の例に示すように、できます:-)。
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 行目を見てください。が値を含むx
null 許容整数変数 (つまり) である場合、結果が返されます。それが value の文字列 (コメントに示されているように) である場合、 .ではなく返されます。int?
1
<null>
"1"
"1"
<null>
注: またvar x = 1;
、最初の行で使用している場合は、実行時エラーが発生します。なんで?割り当てにより、変数が null 許容ではないx
datatypeに変換されるためです。int
コンパイラはここで想定していないため、が追加さint?
れた 2 行目で失敗します。null
オブジェクトを参照しないリテラルだからだと思います。ToString()
が必要object
です。
文字列への追加null
は単純に無視されます。null
(2番目の例では)オブジェクトのインスタンスではないため、ToString()
メソッドさえありません。それはただの文字通りです。
文字列を連結するときとの間string.Empty
に違いはないからです。null
null を渡すこともできますstring.Format
。しかし、 でメソッドを呼び出そうとすると、null
常に がNullReferenceException
発生するため、コンパイラ エラーが発生します。
何らかの理由で本当にやりたい場合は、 をチェックしnull
てから返す拡張メソッドを書くことができますstring.Empty
。しかし、そのような拡張機能は、絶対に必要な場合にのみ使用する必要があります (私の意見では)。
一般的に: 仕様に応じて、パラメーターとして null を受け入れることが有効である場合とそうでない場合がありますが、null でメソッドを呼び出すことは常に無効です。
それが、文字列の場合に + 演算子のオペランドが null になる可能性がある理由です。これは、プログラマーの生活を楽にするための、またはプログラマーが null を処理できないと仮定するための、ちょっとした VB のことです (ごめんなさい)。私はこの仕様に完全に同意しません。'unknown' + 'anything' はまだ 'unknown' である必要があります...