为什么匿名方法中不允许使用out参数?
这不是使用匿名方法的ref或out参数调用方法的欺骗
我想知道为什么在匿名方法中不允许输出参数。 不允许ref参数对我来说更有意义,但out参数不是那么多。
你对此有何看法?
在某些方面,这是一个骗局。 Out
参数是ref
参数。 C#语言使用的值只有一个额外的属性。 不允许它们的原因与ref
参数完全相同。
这里的问题源于在匿名方法中使用匿名方法之外声明的值的效果。 这样做会捕获lambda中的值,并且必然会将其生命周期延长到超出当前函数的寿命。 这与具有固定寿命的out
参数不兼容。
想象一下,例如out
参数引用堆栈上的局部变量。 lambda可以在将来的任意点执行,因此可以在该堆栈帧不再有效时执行。 那么out
参数意味着什么?
这基本上与匿名委托/ lambda表达式的参数是捕获变量这一事实有关,并且捕获ref
/ out
变量在C#/ CLR中没有任何意义,因为它将在内部需要ref
/ out
字段 。 另外,请注意我将这两个关键字配对,因为它们实际上是相同的。
如果你想要一个完整的解释, Eric Lippert在他的博客上详细讨论了这个设计点 。 (特别参见底部附近的段落。)
out
和ref
参数之间的唯一区别是out
参数将应用[out]
标记。 就CLR而言,它们是相同的。
为了实现它,编译器必须生成不支持的ref
字段 。
如果你考虑一下,你会发现允许匿名方法使用out
参数是没有意义的。
下面的代码是什么?
static Func
我在开发一些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); }