何らかの理由で、M1()
はコンパイラエラーを引き起こしますが、同じことを行うM2()
はエラーを引き起こしません。理由は何ですか?
false ==
の使用は、not演算子!
の使用と同じである必要があります。
割り当てられていないローカル変数「i」の使用
class Program {
static void Main(string[] args) {
int x = 8;
M1(x);
M2(x);
} // Main()
public static void M1(Object obj) {
if (false == (obj is int i)) // Causes ERROR on WriteLine
return;
System.Console.WriteLine(i); // Use of unassigned local variable 'i'
}
public static void M2(Object obj) {
if (!(obj is int i)) // OKAY
return;
System.Console.WriteLine(i);
}
} // class Program
ここでの問題は、コンパイラが「trueの場合に確実に割り当てられる」を処理する方法にあります。 _!
_はそれを反転します; _== false
_はしません。したがって、コードの場合:
_if (!(obj is int i))
return;
System.Console.WriteLine(i);
_
コンパイラーは、_obj is int i
_がfalseの場合、_!
_がそれを反転するため、return
でない場合はint
が発生すると推測できます。したがって、i
は後続のコードに安全に「リーク」することができます。
ただし、同じルールは_== false
_には適用されません。人間のコードリーダーと意味的には同じですが、コンパイラーは_!
_と_== false
_を非常に異なるものとして扱います。だから:
_if (false == (obj is int i))
_
コンパイラは、i
の割り当て状態を知ることができないため、エラーが発生します。
これに関する議論については、 _(x is T y) == false
_ の 誤った「割り当てられていないローカル変数の使用」」を参照してください。
話の教訓:C#パターンを使用する場合は、false
との比較を避け、_!
_を使用してください。
[〜#〜]編集[〜#〜]
ここでは、_== false
_は特別な場合ではないことに注意してください。 _==
_を使用すると、コンパイラーが「trueの場合に確実に割り当てられる」と判断する機能が失われます。たとえば、次のコードはコンパイルされます。
_object x = 1;
if (!(x is bool y))
return 0;
var z = y;
_
ただし、_== true
_を追加すると、次の機能はなくなります。
_object x = 1;
if (!(x is bool y == true))
return 0;
var z = y; // error: use of an unassigned variable
_
EDIT2
ちなみに、if (expression == false)
が読みにくいと感じたために、if (!expression)
を使用する人は、---(構文、if !(expression)
がC#8 で考慮されます。
良い発見、これが私が思うことです。これは間違いなく修正できるものですが、私はその理由を見つけようとしていることに注意してください。これは正確な答えではないことに注意してください。ただ言って!
この問題を引き起こすのは_false ==
_だけでなく、_== true
_によってi
がどちらのブランチでも使用できなくなるため、先に進んでこれを作成しました。
_var x = obj is int i;
if(x) Console.WriteLine(i);
_
同じエラーが発生します。 x
が真であるかどうかがわかるように、i
を初期化する必要がありますよね? x
の値をいじり始めない限り!ここでx
は定数ではないため、ifステートメントを実行する前にx
が常にtrueのままであることを保証することはできません。
ただし、コンパイラはコンパイル時に定数値と式を計算できます。ここで何が起こっているのかわかりませんが、私が思うのは
if((obj is int i) == false)
ここで_==
_演算子は、パターンマッチングの結果とifステートメントの評価の間にギャップを置きます。したがってエラーになります。 _!
_演算子が正常に機能する理由がわかりません。おそらく、その部分を最適化したのに、これを最適化するのを忘れたのでしょうか。 ;)
これはコンパイラのセマンティック分析フェーズに関連していると思います。その仕事は、コードの意味を検証し、コードの実行方法を決定することです。何か問題がある場合、未定義の動作の可能性がある場合、またはまったく意味のないものがある場合、失敗してあなたはコンパイル時エラーが発生します。続きを読む コンパイラ設計のフェーズ