在声明点使用变量作为输出参数

Using a variable as an out argument at point of declaration

在阅读 comment 的答案时,我看到了以下用于声明和初始化变量的结构:

int variable = int.TryParse(stringValue, out variable) ? variable : 0;

这在 C# 中是否被允许、正确且定义明确? 引擎盖下发生了什么?下面是怎么回事?

  1. variable是否先初始化为零?
  2. 然后传给int.TryParse(赋值)?
  3. 然后可选地阅读(if int.TryParse return true)?
  4. 然后,再一次 assigned/initialized?

int variable 声明了 variable,而 out variable 必然会初始化它。在任何地方使用 variable 之前,这两件事都必须发生,并且由于 out 声明,这是正确的。

正如 Lasse V. Carlsen 所指出的,从 TryParse's documentation 开始,如果转换失败,TryParse 将默认为其分配 0 的值:

When this method returns, [return] contains the 32-bit signed integer value equivalent of the number contained in s, if the conversion succeeded, or zero if the conversion failed. (emph. mine)

如果你展开三元函数,你会看到:

int variable;
if (int.TryParse(stringValue, out variable))
    variable = variable;
else
    variable = 0;

这本身就是一个合法的表达方式。两条路径是:

  • TryParse 将值赋值给 variable 和 returns true,导致 variable 赋值给自身
  • TryParsevariable 初始化为 0 和 returns false,导致 variable 被三元条件赋值为零

虽然这不是特别清晰的代码,但我不建议这样做。

我还没有打开 Visual Studio 来尝试这个,但是是的,这是允许的。

这完全取决于 "stringValue" 变量。如果它可解析为整数,则 int.TryParse 将 return 为真,并且 [variable] 将具有整数值。如果不是,则 variable 将设置为 0。

这是否有助于编写可读代码?显然不是。

这是一个恰好有效的技巧,因为它只是对普通 if 语句的重写。此代码等效于:

int variable;
if (int.TryParse(stringVariable, out variable))
    variable = variable;
else
    variable = 0;

顺序如下:

int.TryParse 被调用,variable 在此之前未初始化,但也不必初始化。 out 参数不需要明确分配的变量。作为方法执行的一部分,variable 将被赋予一个值,而 int.TryParse 将 return truefalse.

如果方法 returns true 那么 表达式 的结果将是 variable 因此我们基本上会执行 variable = variable.

如果方法 returns false 那么 表达式 的结果将改为 0,并且 variable现在将被赋予值 0,而不管它作为 int.TryParse 的一部分被赋予什么。然而,在这种情况下,这不会改变变量,因为 int.TryParse 已经给 variable 一个默认值,当它 returns false 也恰好是 0.

这基本上是一种将所有内容都放在一行中的方法。

就我个人而言,我会这样编写代码:

int variable;
int.TryParse(stringValue, out variable);

是的,你适合处决。您还可以查看此处生成的 MSIL

C# 代码

 string stringValue = "5";
 int variable = int.TryParse(stringValue, out variable) ? variable : 0;

已生成 MSIL

1.  IL_0000:  nop    
2.  IL_0001:  ldstr      "5" // load string
3.  IL_0006:  stloc.0
4.  IL_0007:  ldloc.0
5.  IL_0008:  ldloca.s   variable
6.  IL_000a:  call       bool [mscorlib]System.Int32::TryParse(string, int32&)
7.  IL_000f:  brtrue.s   IL_0014
8.  IL_0011:  ldc.i4.0
9.  IL_0012:  br.s       IL_0015
10. IL_0014:  ldloc.1
11. IL_0015:  stloc.1
12. IL_0016:  ret

这阐明了它在幕后所做的事情。

语句 5 正在将变量分配到堆栈上。 语句 6 正在调用该方法。 语句 7、8、9 实际上是在执行 bool 表达式。