为什么匿名方法中不允许使用out参数?

这不是使用匿名方法的ref或out参数调用方法的欺骗

我想知道为什么在匿名方法中不允许输出参数。 不允许ref参数对我来说更有意义,但out参数不是那么多。

你对此有何看法?

在某些方面,这是一个骗局。 Out参数是ref参数。 C#语言使用的值只有一个额外的属性。 不允许它们的原因与ref参数完全相同。

这里的问题源于在匿名方法中使用匿名方法之外声明的值的效果。 这样做会捕获lambda中的值,并且必然会将其生命周期延长到超出当前函数的寿命。 这与具有固定寿命的out参数不兼容。

想象一下,例如out参数引用堆栈上的局部变量。 lambda可以在将来的任意点执行,因此可以在该堆栈帧不再有效时执行。 那么out参数意味着什么?

这基本上与匿名委托/ lambda表达式的参数是捕获变量这一事实有关,并且捕获ref / out变量在C#/ CLR中没有任何意义,因为它将在内部需要ref / out 字段 。 另外,请注意我将这两个关键字配对,因为它们实际上是相同的。

如果你想要一个完整的解释, Eric Lippert在他的博客上详细讨论了这个设计点 。 (特别参见底部附近的段落。)

outref参数之间的唯一区别是out参数将应用[out]标记。 就CLR而言,它们是相同的。

为了实现它,编译器必须生成不支持的ref 字段

如果你考虑一下,你会发现允许匿名方法使用out参数是没有意义的。

下面的代码是什么?

 static Func Mess(out object param) { param = "Original"; return i => param = i; } static Func MessCaller() { object local; return Mess(out local); } static vouid Main() { Console.WriteLine(MessCaller()("New")); //The local variable that the lambda expression writes to doesn't exist anymore. } 

我在开发一些error handling代码时遇到了这个难题。 我想将引用(out)传递给将被记录的错误消息。 这使我的匿名方法有机会执行多个检查,每个检查都根据需要设置错误消息。

我最后为匿名方法编写了一个新的包装器,它的工作方式不同。 但我认为对某人有一些价值的是,我可以简单地创建一个具有out参数的私有方法,并定义一个委托,并使我的代码使用它。 希望这有助于/激励某人。

  protected delegate void OutStringDelegate(int divider, out string errorText); protected void codeWrapper(int divider, OutStringDelegate del) { string ErrorMessage = "An Error Occurred."; try { del(divider, out ErrorMessage); } catch { LogError(ErrorMessage); } } public void UseWrapper(int input) { codeWrapper(input, codeToCall); } private int somePrivateValue = 0; private void codeToCall(int divider, out string errorMessage) { errorMessage = "Nice Error Message here!"; somePrivateValue = 1 / divider; // call me with zero to cause error. } private void LogError(string msg) { Console.WriteLine(msg); }