What's the benefit of var patterns in C#7?
The var pattern was very frequently discussed in the C# language repository given that it’s not perfectly clear what its use case is and given the fact that is var x
does not perform a null check while is T x
does, making it appear rather useless.
However, it is actually not meant to be used as obj is var x
. It is meant to be used when the left hand side is not a variable on its own.
Here are some examples from the specification. They all use features that are not in C# yet but this just shows that the introduction of the var pattern was primarly made in preparation for those things, so they won’t have to touch it again later.
The following example declares a function Deriv
to construct the derivative of a function using structural pattern matching on an expression tree:
Expr Deriv(Expr e)
{
switch (e) {
// …
case Const(_): return Const(0);
case Add(var Left, var Right):
return Add(Deriv(Left), Deriv(Right));
// …
}
Here, the var
pattern can be used inside the structures to “pull out” elements from the structure. Similarly, the following example simplifies an expression:
Expr Simplify(Expr e)
{
switch (e) {
case Mult(Const(0), _): return Const(0);
// …
case Add(Const(0), var x): return Simplify(x);
}
}
As gafter writes here, the idea is also to have property pattern matching, allowing the following:
if (o is Point {X is 3, Y is var y})
{ … }
Without checking the design notes on Github I'd guess this was added more for consistency with switch
and as a stepping stone for more advanced pattern matching cases,
From the original What’s New in C# 7.0 post :
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.
And the recent dissection post by 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);
}
}
The warning righ before that snippet is also significant:
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.".
According to Christian Nagel :
The advantage is that the variable declared with the var keyword is of the real type of the object,