web-dev-qa-db-ja.com

C#7のvarパターンの利点は何ですか?

C#7のvarパターンの使用例がわかりません。 [〜#〜] msdn [〜#〜]

varパターンとのパターンマッチは常に成功します。その構文は

expr is var varname

exprの値は、常にvarnameという名前のローカル変数に割り当てられます。 varnameは、exprと同じ型の静的変数です。

私の意見では、MSDNの例は、特にifが冗長であるため、ほとんど役に立ちません。

object[] items = { new Book("The Tempest"), new Person("John") };
foreach (var item in items) {
  if (item is var obj)
    Console.WriteLine($"Type: {obj.GetType().Name}, Value: {obj}"); 
}

ここでは、利点は見当たりません。ループ変数itemに直接アクセスする場合、これもObject型です。 ifは決してfalseではないため、混乱を招きます。

var otherItem = itemを使用するか、itemを直接使用できます。誰かがユースケースをよりよく説明できますか?

28
Tim Schmelter

var patternC#言語リポジトリ で非常に頻繁に議論されました。 is var xはnullチェックを実行しないが、is T xはnullチェックを実行するため、かなり役に立たないように見えます。

ただし、実際にはobj is var xとして使用するためのものではありません。左側がnot単独の変数である場合に使用することを意図しています。

仕様 の例をいくつか示します。それらはすべて、C#にはない機能yetを使用しますが、これは、varパターンの導入が主にそれらの準備のために行われたことを示しているため、後でもう一度触れる必要はありません。

次の例では、関数Derivを宣言して、式ツリーで構造パターンマッチングを使用して、関数の 微分 を構築します。

Expr Deriv(Expr e)
{
    switch (e) {
        // …
        case Const(_): return Const(0);
        case Add(var Left, var Right):
            return Add(Deriv(Left), Deriv(Right));
        // …
}

ここで、varパターンを構造内で使用して、構造から要素を「引き出す」ことができます。同様に、次の例は式を単純化します。

Expr Simplify(Expr e)
{
    switch (e) {
        case Mult(Const(0), _): return Const(0);
        // …
        case Add(Const(0), var x): return Simplify(x);
    }
}

gafterがここに書いている のように、アイデアはプロパティパターンマッチングを持ち、以下を可能にすることでもあります。

if (o is Point {X is 3, Y is var y})
{ … }
15
poke

Githubの設計ノートを確認せずに、これはswitchとの一貫性のために、さらに高度なパターンマッチングの場合の踏み台として追加されたと思います。

オリジナルから C#7.0の新機能 post:

Var x(xは識別子)の形式のVarパターン。常に一致し、入力の値を入力と同じ型の新しい変数xに単純に入れます。

そして、最近の 解剖記事 Sergey Teplyakovによる:

何が起こっているかを正確に知っているなら、このパターンが役に立つかもしれません。式内に一時変数を導入するために使用できます。このパターンは、基本的にオブジェクトの実際のタイプを使用して一時変数を作成します。

public void VarPattern(IEnumerable<string> s)
{
    if (s.FirstOrDefault(o => o != null) is var v
        && int.TryParse(v, out var n))
    {
        Console.WriteLine(n);
    }
}

そのスニペットの前の警告も重要です:

リリースモードでのみ動作が異なる理由は明らかではありません。しかし、私はすべての問題が同じバケツに分類されると思います:機能の最初の実装は次善です。しかし、Neal Gafterによるこのコメントに基づいて、これは変更される予定です。「パターンマッチングの低下コードはゼロから書き直されています(再帰パターンもサポートするため)。ここで求める改善のほとんどは「無料「新しいコードでは。しかし、その書き換えがプライムタイムの準備が整うまでにはしばらく時間がかかります。」.

Christian Nagel によると:

利点は、varキーワードで宣言された変数がオブジェクトの実際の型であり、

14

私がオフハンドだと思うことができるのは、2つの同一のコードブロック(たとえば、単一のswitch)を記述した場合、1つはexpr is object a用、もう1つはexpr is null用。

expr is var aに切り替えることでブロックを結合できます。

また、何らかの理由で、すでにコーナーに自分自身を書いており、常にパターンマッチを生成することを期待しているが、「すべてにマッチ」パターンを発行したいコード生成シナリオで役立つ場合があります。

ほとんどの場合、それは真実であり、varパターンの利点は明確ではなく、悪い考えですらあります。ただし、temp型変数で匿名型をキャプチャする方法としては、うまく機能します。この例がこれを説明できることを願っています。以下に注意してください。nullケースを追加すると、varがnullになることが回避され、nullチェックが不要になります。

        var sample = new(int id, string name, int age)[] { 
                                                          (1, "jonas", 50),                                                                                                                            
                                                          (2, "frank", 48) };

        var f48 = from s in sample 
                  where s.age == 48 
                  select new { Name = s.name, Age = s.age };

        switch(f48.FirstOrDefault())
        {
            case var choosen when choosen.Name == "frank":
                WriteLine(choosen.Age);
                break;
            case null:
                WriteLine("not found");
                break;
        }
0
Jonas Brandel