c# – Task.Run如何用action和ref变量名来编写它

c# – Task.Run如何用action和ref变量名来编写它,第1张

概述我代表一个“小”的语法问题,无法弄清楚如何正确地写出我想要的东西. 我有以下方法: public void DoSomeMagic(string foo, ref string bar){ //DoSomeMagic...} 现在我想在Task.Run中卸载这段代码我通常会编写以下代码: public async void Button_Click(object sender, Eve 我代表一个“小”的语法问题,无法弄清楚如何正确地写出我想要的东西.

我有以下方法:

public voID DoSomeMagic(string foo,ref string bar){    //DoSomeMagic...}

现在我想在Task.Run中卸载这段代码我通常会编写以下代码:

public async voID button_Click(object sender,EventArgs args){    string foo = "Hello Foo";    string bar = "Hello bar";    await Task.Run(() => DoSomeMagic(foo,ref bar));}

这不编译告诉我:“不能在匿名方法体内使用’ref’或’out’参数’bar’”

所以我想为什么甚至做()=>因为我只是调用方法,我可以将它减少到这个:

Task.Run(DoSomeMagic(foo,ref bar));

这再次没有编译告诉我:无法解析方法’Run(voID)’,候选者是:Run(Action)和Run(Func)

所以再一次没有问题Visual Studio你的需求是我的命令.

并将代码更改为:

Task.Run((Action)DoSomeMagic(foo,ref bar));

再次没有编译告诉我:不能将’voID’类型的表达式转换为’Action’类型,

好的,这开始变得棘手……

我试图而不是返回voID我将尝试int并转换为Func
给我错误:无法将’int’类型的表达式转换为’Func’类型

看到那个人来了,但我想让我们试一试:

所以我尝试了以下方法:

public Action CallDoSomeMagic(string foo,ref string bar){    //DoSomeMagic...    return new Action(() => DoSomeMagic(foo,ref bar));}Task.Run(CallDoSomeMagic);

但这又给了我一个消息“不能在匿名方法体内使用’ref’或’out’参数’bar’”

由于每次尝试我的头痛都在增加,我想你们可以帮助我.
它甚至可能吗?

解决方法 正如消息所说:你不能这样做.

您可以获取参数值的副本,并捕获该参数值,例如:

public Action CallDoSomeMagic(string foo,ref string bar){    var snapshot = bar;    return new Action(() => DoSomeMagic(foo,ref snapshot));}

但请注意,通过条形图在调用者外部看不到快照更新.

原因有两方面:

首先,在lambda上使用的捕获变量成为编译器生成的上下文类中的字段.这适用于非ref / out参数,因为它们已经具有复制语义.因此,对于我的快照示例,这实际上是:

var ctx = new CompilerGeneratedContextClassWithHorriblename();ctx.foo = foo;ctx.snapshot = bar;return new Action(ctx.CompilerGeneratedMethod);

CompilerGeneratedMethod是:

DoSomeMagic(foo,ref snapshot);

这对于refs是不可能的,因为你基本上需要该字段作为对字符串引用的引用,这是……凌乱的.

但更重要的是:考虑来电者的生命周期.这可能是:

voID SomeMethod() {    string s = "abc";    CallDoSomeMagic("def",ref s);}

请特别注意,即使稍后调用委托,代码也需要工作 – 事实上我们可能会在您的情况下期望它,因为它涉及Task和async.现在:如果SomeMethod退出:对字符串引用指向的引用在哪里?提示:它只是堆栈中的任意位置,现在超出范围.

只是为了给出一个更简单的解决方法:不要传递ref string bar,而是考虑传递SomeType obj,其中obj.bar是你想要的字符串;即

public Action CallDoSomeMagic(string foo,SomeType obj){    return new Action(() => DoSomeMagic(foo,obj));}public voID DoSomeMagic(string foo,SomeType obj){    // read and write obj.bar here}

请注意,如果您愿意,也可以将foo移动到obj.Foo.

总结

以上是内存溢出为你收集整理的c# – Task.Run如何用action和ref变量名来编写它全部内容,希望文章能够帮你解决c# – Task.Run如何用action和ref变量名来编写它所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1249161.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-07
下一篇2022-06-07

发表评论

登录后才能评论

评论列表(0条)

    保存