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

发布于 2024-08-08 18:39:56 字数 301 浏览 12 评论 0原文

这不是调用来自匿名方法的带有 ref 或 out 参数的方法

我想知道为什么匿名方法中不允许使用 out 参数。不允许 ref 参数对我来说更有意义,但 out 参数就没那么有意义了。

你对此有何看法

This is not a dupe of Calling a method with ref or out parameters from an anonymous method

I am wondering why out parameters are not allowed within anonymous methods. Not allowing ref parameters makes a bit more sense to me, but the out parameters, not as much.

what are your thoughts on this

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

她说她爱他 2024-08-15 18:39:56

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

这里的问题源于在匿名方法内使用匿名方法外部声明的值的影响。这样做将捕获 lambda 内的值,并在必要时任意将其生命周期延长到当前函数的生命周期之外。这与具有固定生命周期的 out 参数不兼容。

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

In some ways this is a dupe. Out parameters are ref parameters. There is simply an extra attribute on the value that is used by the C# language. The reason for disallowing them is the exact same as ref parameters.

The problem here originates with the effect of using a value declared outside the anonymous method within the anonymous method. Doing so will capture the value within the lambda and out of necessity arbitrarily extend its lifetime beyond that of the current function. This is not compatible with out parameters which have a fixed lifetime.

Imagine for instance that the out parameter referred to a local variable on the stack. The lambda can execute at any arbitrary point in the future and hence could execute when that stack frame was no longer valid. What would the out parameter mean then?

转身以后 2024-08-15 18:39:56

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

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

This is basically to do with the fact that parameters of an anonymous delegate/lambda expressions are captured variables, and capturing ref/out variables doesn't make any sense in C#/the CLR, since it would require ref/out fields internally. Also, note that I pair both these keywords because they are effectively the same.

If you want a complete explanation, Eric Lippert discussed this design point in detail on his blog. (See the paragraphs near the bottom in particular.)

德意的啸 2024-08-15 18:39:56

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

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

如果您考虑一下,您就会意识到允许匿名方法使用 out 参数是没有意义的。

下面的代码会做什么?

static Func<object, object> Mess(out object param) {
    param = "Original";
    return i => param = i;
}
static Func<object, object> 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.
}

The only difference between out and ref parameters is that an out parameter will have an [out] token applied to it. They're the same thing as far as the CLR is concerned.

In order to implement it, the compiler would have to generate ref fields, which are not supported.

If you think about it, you'll realize that it makes no sense to allow an anonymous method to use an out parameter.

What would the following code to?

static Func<object, object> Mess(out object param) {
    param = "Original";
    return i => param = i;
}
static Func<object, object> 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.
}
毁我热情 2024-08-15 18:39:56

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

我最终为匿名方法编写了一个新的包装器,其工作方式有所不同。但我认为对某人可能有价值的是,我可以简单地创建一个具有 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);
    }

I came across this conundrum whilst developing some error handling code. I wanted to pass a reference (out) to an error message that would get logged. This gave my anonymous methods a chance to perform multiple checks, each setting the error message as necessary.

I ended up writing a new wrapper for the anonymous method that worked differently. But what I thought might be of some value to someone, is that I could have simply made a private method that had an out parameter, and defined a delegate, and made my code use that. Hope this helps / inspires somebody.

    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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文