C#7 中的 var 模式有什么好处?

What's the benefit of var patterns in C#7?

我不明白 var 模式在 C#7 中的用例。 MSDN:

A pattern match with the var pattern always succeeds. Its syntax is

expr is var varname

where the value of expr is always assigned to a local variable named varname. varname is a static variable of the same type as 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}"); 
}

这里我看不出有什么好处,如果你直接访问也是Object类型的循环变量item,你也可以得到同样的好处。 if 也令人困惑,因为它从来不是 false

我可以直接使用var otherItem = itemitem。 有人可以更好地解释用例吗?

我唯一能想到的是,如果您发现自己编写了两个相同的代码块(比如一个 switch),一个用于 expr is object a,另一个用于 expr is null.

您可以通过切换到 expr is var a 来组合方块。

它在代码生成场景中也很有用,在这种情况下,无论出于何种原因,您已经将自己逼入绝境,并且总是希望生成模式匹配,但现在想要发出 "match all" 模式。

如果不检查 Github 上的设计说明,我猜这是为了与 switch 保持一致而添加的,并作为更高级模式匹配案例的垫脚石,

原文What’s New in C# 7.0post:

Var patterns of the form var x (where x is an identifier), which always match, and simply put the value of the input into a fresh variable x with the same type as the input.

最近 dissection post 作者:Sergey Teplyakov :

if you know what exactly is going on you may find this pattern useful. It can be used for introducing a temporary variable inside the expression: This pattern essentially creates a temporary variable using the actual type of the object.

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

该片段之前的警告也很重要:

It is not clear why the behavior is different in the Release mode only. But I think all the issues falls into the same bucket: the initial implementation of the feature is suboptimal. But based on this comment by Neal Gafter, this is going to change: "The pattern-matching lowering code is being rewritten from scratch (to support recursive patterns, too). I expect most of the improvements you seek here will come for "free" in the new code. But it will be some time before that rewrite is ready for prime time.".

根据Christian Nagel

The advantage is that the variable declared with the var keyword is of the real type of the object,

var 模式C# language repository 中被频繁讨论,因为它的用例是什么并不完全清楚,并且考虑到 is var x不执行 null 检查而 is T x 执行,使它看起来相当无用。

然而,它实际上并不意味着用作obj is var x。当左侧 本身不是 变量时使用它。

以下是 the specification 中的一些示例。他们都使用了 C# yet 中没有的功能,但这只是表明 var 模式的引入主要是为这些事情做准备,因此他们不必再次接触它稍后。

以下示例声明了一个函数 Deriv 以在表达式树上使用结构模式匹配构造函数 the derivative

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 writes here一样,思路也是属性模式匹配,允许如下:

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

在大多数情况下确实如此,var 模式的好处并不清楚,甚至可能是个坏主意。然而,作为一种在临时变量中捕获匿名类型的方法,它的效果很好。 希望这个例子可以说明这一点: 请注意下面,添加 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;
        }