web-dev-qa-db-ja.com

var / nullの奇妙な動作をするスイッチ

次のコードを考えます:

_string someString = null;
switch (someString)
{
    case string s:
        Console.WriteLine("string s");
        break;
    case var o:
        Console.WriteLine("var o");
        break;
    default:
        Console.WriteLine("default");
        break;
}
_

なぜswitchステートメントが_case var o_で一致するのですか?

_case string s_は(事実上)_s == null_がfalseと評価されるため、_(null as string) != null_が一致しないことを理解しています。 VS CodeのIntelliSenseは、ostringであることを教えてくれます。何かご意見は?


似たもの: C#7 nullチェック付きスイッチケース

90
budi

明示的な型にswitchを使用するcaseステートメントに一致するパターン内では、問題の値がその特定の型か派生型かを尋ねています。 isとまったく同じです

switch (someString) {
  case string s:
}
if (someString is string) 

nullには型がないため、上記の条件のいずれも満たしていません。どちらの例でも、someStringの静的型は役に立たない。

ただし、パターンマッチングではvarタイプはワイルドカードとして機能し、nullを含むすべての値と一致します。

ここでのdefaultケースはデッドコードです。 case var oは、nullまたは非nullの任意の値に一致します。デフォルト以外の場合は常にデフォルトの場合よりも優先されるため、defaultはヒットしません。 ILを見ると、放出されていないことがわかります。

一見すると、これが警告なしにコンパイルされるのは奇妙に思えるかもしれません(間違いなく私を捨てました)。ただし、これは1.0に戻るC#の動作と一致しています。コンパイラーは、ヒットしないことを自明に証明できる場合でも、defaultの場合を許可します。例として、次のことを検討してください。

bool b = ...;
switch (b) {
  case true: ...
  case false: ...
  default: ...
}

ここでは、defaultはヒットしません(1または0以外の値を持つboolであっても)。しかし、C#は警告なしで1.0からこれを許可しています。ここでのパターンマッチングは、この動作と一致しています。

69
JaredPar

ここで複数のTwitterコメントをまとめています。これは実際には私にとって初めてのことであり、jaredparがより包括的な回答でジャンプすることを望んでいますが、私が理解しているように短いバージョン:

_case string s:
_

if(someString is string) { s = (string)someString; ...またはif((s = (someString as string)) != null) { ... }として解釈されます-どちらもnullテストを含みます-あなたの場合は失敗します;逆に:

_case var o:
_

ここで、コンパイラはostringとして解決しますo = (string)someString; ...-nullテストなし、にもかかわらず似ているという事実表面的には、型を提供するコンパイラーだけで。

最後に:

_default:
_

ここではに到達できません。上記のケースがすべてをキャッチするためです。これは、到達不能コードの警告を出さなかったという点で、コンパイラのバグである可能性があります。

私はこれが非常に微妙で微妙で、混乱していることに同意します。しかし、明らかに_case var o_シナリオはnull伝播(_o?.Length ?? 0_など)で使用します。 _var o_と_string s_の間でこれがうまく機能するのは奇妙だと思いますveryします。

22
Marc Gravell

その理由は case <Type>は、静的(コンパイル時)タイプではなく、動的(実行時)タイプに一致します。 nullには動的タイプがないため、stringに一致しません。 varは単なるフォールバックです。

(短い回答が好きなので投稿)

14
Mehrdad