この質問は以前に回答されたかもしれませんが、Word if
が頻繁に発生するため、見つけるのが困難です。
この例は意味をなしません(式は常に真です)が、私の質問を示しています。
このコードが有効な理由:
StringBuilder sb;
if ((sb = new StringBuilder("test")) != null) {
Console.WriteLine(sb);
}
しかし、このコードはそうではありません:
if ((StringBuilder sb = new StringBuilder("test")) != null) {
Console.WriteLine(sb);
}
while
ステートメントに関する同様の質問を見つけました。受け入れられた答えは、while
ステートメントでは、変数が各ループで定義されることを意味すると述べています。しかし、私のif
ステートメントの例では、そうではありません。
では、これが許可されていない理由は何ですか?
これは、C#言語仕様のセクション8.5.1が原因です。状態:
さらに、ローカル変数宣言の変数初期化子は、宣言の直後に挿入される割り当てステートメントに正確に対応します。
これは基本的に次のことを意味します:
StringBuilder sb = new StringBuilder("test")
実際には、次とまったく同じことを実行しています。
StringBuilder sb; sb = new StringBuilder("test")
そのため、割り当ては単一の式ではなく、local-variable-declaratorであるステートメントであるため、!= null
に対するチェックの戻り値はなくなりました。識別子で構成されます式が後に続く。
言語仕様では、この例を次のように示しています。
void F() {
int x = 1, y, z = x * 2;
}
以下とまったく同じです。
void F() {
int x; x = 1;
int y;
int z; z = x * 2;
}
C#7のパターンマッチング を試してください。
あなたの例を使用して:
if (new StringBuilder("test") is var sb && sb != null) {
Console.WriteLine(sb);
}
これは、ステートメントと式の違いに関係しています。式には値がありますが、ステートメントにはありません。
例を使用して、次の分類に注意してください。
StringBuilder sb; // statement
sb = new StringBuilder("test") // expression
StringBuilder sb = new StringBuilder("test"); // statement
中央部分のみが式であることに注意してください。
次に、条件ステートメントに移ります。等しくない演算子を使用するための構文は次のとおりです。
expression != expression
したがって、!=
の両側には、実際に値を持つものが必要です(これは理にかなっています)。エルゴ、あなたは演算子の両側にステートメントを持つことはできません。これが、コードの1つのバージョンが機能する一方で、他のバージョンが機能しない理由です。
の代わりに:
if ((StringBuilder sb = new StringBuilder("test")) != null) {
Console.WriteLine(sb);
}
次のように書くこともできます:
for (StringBuilder sb = new StringBuilder("test"); sb != null; sb = null) {
Console.WriteLine(sb);
}
このforループは、変数がnullでない場合に1回実行されます。ループの最後で、一時変数はnullに設定されます。その後、ループ条件は偽と評価され、閉じ括弧が実行された後、次のステートメントが続行されます。 ifステートメントが元々意図していた通り。