web-dev-qa-db-ja.com

値型タプルで「is」演算子を使用するとエラーが発生する

object変数が(int, int)であるかどうかを確認しようとしています。そうである場合は、キャストされた変数を使用するため、以下のコードを試しました。

//this one gives the error
public void MyMethodWithIs(object val)
{
    if(val is (int id, int name) pair)
    {
        ConsoleWriteLine($"{pair.id}, {pair.name}");
    }
}

//This one works
public void MyMethodWithAs(object val)
{
    var pair = val as (int id, int name)?;
    if(pair!=null)
    {
        ConsoleWriteLine($"{pair.id}, {pair.name}");
    }
}

MyMethodWithIsメソッドを使用すると、エディターで以下のエラーが発生します。

タイプに適した分解インスタンスまたは拡張メソッドが見つかりませんでした

私の質問

なぜ1つはうまく機能するが、もう1つはまったくエラーを返すのですか? MyMethodWithIsの方が読みやすく、自分のケースでの使用に適していると思いますが、エラーが発生したため使用できません。

17
ilkerkaran

C#8のパターンマッチング機能を使用すると、次のように記述できます。

_if (val is (int id, int name))
{
    Console.WriteLine($"id: {id}; name: {name}");
}
_

ただし、このボックスはidおよびnameであり、これは驚くべきことです。 これを最適化するための提案 があります。

C#8の下で、これを書くことができます:

_if (val is ValueTuple<int, int> pair)
{
    Console.WriteLine($"id: {pair.Item1}; name: {pair.Item2}");
}
_

もちろん、少しわかりやすくすることもできます。

_if (val is ValueTuple<int, int> pair)
{
    var (id, name) = pair;
    Console.WriteLine($"id: {id}; name: {name}");
}
_

ValueTupleをインラインで分解することもできます。

_if (val is ValueTuple<int, int>(var id, var name))
{
    Console.WriteLine($"id: {id}; name: {name}");
}
_

...これは少し恐ろしいですが、 合法であるように見えます

val is (int, int) pair)が機能することを期待していたかもしれませんが、このケースは(まだ)誰も設計していないようです。

19
canton7