out var 声明

C#中的一个常见模式是使用 bool TryParse(object input, out object value) 来安全地解析对象。

out var 声明是一个提高可读性的简单功能。它允许变量在作为 out 参数传递的同时声明。

以这种方式声明的变量的范围限定在声明它的位置的主体的其余部分。

在 C#7.0 之前使用 TryParse,你必须声明一个变量以在调用函数之前接收该值:

Version < 7
int value;
if (int.TryParse(input, out value)) 
{
    Foo(value); // ok
}
else
{
    Foo(value); // value is zero
}

Foo(value); // ok

在 C#7.0 中,你可以内联传递给 out 参数的变量的声明,从而无需单独的变量声明:

Version >= 7
if (int.TryParse(input, out var value)) 
{
    Foo(value); // ok
}
else
{
    Foo(value); // value is zero
}

Foo(value); // still ok, the value in scope within the remainder of the body

如果不需要函数在 out 中返回的某些参数,则可以使用 discard 运算符 _

p.GetCoordinates(out var x, out _); // I only care about x

out var 声明可以与任何已有 out 参数的现有函数一起使用。函数声明语法保持不变,并且不需要额外的要求来使函数与 out var 声明兼容。这个功能只是语法糖。

out var 声明的另一个特性是它可以与匿名类型一起使用。

Version >= 7
var a = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var groupedByMod2 = a.Select(x => new
                                  {
                                      Source = x,
                                      Mod2 = x % 2
                                  })
                     .GroupBy(x => x.Mod2)
                     .ToDictionary(g => g.Key, g => g.ToArray());
if (groupedByMod2.TryGetValue(1, out var oddElements))
{
    Console.WriteLine(oddElements.Length);
}

在此代码中,我们使用 int 键和匿名类型值数组创建 Dictionary。在之前的 C#版本中,这里不可能使用 TryGetValue 方法,因为它要求你声明 out 变量(它是匿名类型!)。但是,使用 out var,我们不需要明确指定 out 变量的类型。

限制

请注意,out var 声明在 LINQ 查询中的用途有限,因为表达式被解释为表达式 lambda 体,因此引入的变量的范围仅限于这些 lambdas。例如,以下代码将不起作用:

var nums = 
    from item in seq
    let success = int.TryParse(item, out var tmp)
    select success ? tmp : 0; // Error: The name 'tmp' does not exist in the current context

参考