为什么在使用Linq时需要初始化out变量?

本文关键字:初始化 out 变量 Linq 为什么 | 更新日期: 2023-09-27 18:05:31

假设我有一个字符串,我想把它转换成整数,我会做

int i;
int.TryParse(someString, out i);

现在我想在Linq查询中做同样的事情:

int i;
var numbers =
   from s in someStrings
   where int.TryParse(s, out i)
   select i;

但是它拒绝编译,并报错

CS0165未赋值局部变量'i'的使用

当我将I初始化为任意值时,它会按预期编译和工作。但我为什么要这么做?

为什么在使用Linq时需要初始化out变量?

查询表达式翻译成:

var numbers = someStrings.Where(s => int.TryParse(s, out i))
                         .Select(s => i);

现在,我们知道从Where调用的lambda表达式创建的委托将在从Select调用的lambda表达式创建的委托之前执行,但编译器不会。实际上,您可以轻松地编写自己的扩展方法,而不遵守该规则:

public static IEnumerable<T> Where<T>(
    this IEnumerable<T> source,
    Func<T, bool> predicate)
{
    // I can't be bothered to check the predicate... let's just return everything
    return source;
}

在这一点上,使用正常的Select调用,返回i的委托将被执行,而无需为其分配值。

基本上,明确赋值规则是故意相当保守的,避免对方法做什么做任何假设等。

编译成一对lambda表达式,传递给Where()Select()

编译器不知道Where()Select()做什么,也不能证明Where()的lambda总是在Select()之前运行。

编译器直到运行时才能确定是否有任何记录返回。所以为了让i有一个确定的值,1必须被显式赋值。只是想"如果我的查询返回没有行,我会是什么?"