简体   繁体   English

如何在 lambda 表达式中传递 ref 参数? - 线程问题

[英]How to pass a ref parameter inside lambda expression? - Thread issue

I have a method to be called.我有一个方法可以调用。

public void RecordConversation(ref ChannelResource cr)
{
    VoiceResource RecordResource = TServer.GetVoiceResource();
    RecordResource.MaximumTime = 6000;
    RecordResource.MaximumSilence = 6000;
    RecordResource.TerminationDigits = "";
}

To call it in a thread在线程中调用它

Thread recordThread = new Thread(() => RecordConversation(ref ChanResource));
recordThread.Start();

Of course we get an error.当然,我们会得到一个错误。

Cannot use ref or out parameter 'ChanResource' inside an anonymous method, lambda expression, or query expression不能在匿名方法、lambda 表达式或查询表达式中使用 ref 或 out 参数“ChanResource”

How to fix it?如何解决?

Why that error?为什么会出现这个错误?

The scope of the parameters of an anonymous method is the anonymous-method-block .匿名方法的参数范围anonymous-method-block

( Emphasis mine ) 强调我的

lambda expressions are essentially the same as anonymous method. lambda 表达式本质上与匿名方法相同。

As per the doc, the scope of the parameters is limited to its block.根据文档,参数的范围仅限于其块。

But ref and out are outside the scope and hence that error.但是refout超出了范围,因此出现了错误。 I recommend you not to use ref , as parameters are by default passed by value, and in case of reference type, the value of the reference is passed.我建议你不要使用ref ,因为参数默认是按值传递的,如果是引用类型,则传递引用

You can modify the parameter directly to reflect that change.您可以直接修改参数以反映该更改。

You can't use ref .你不能使用ref See this very same question .看到这个非常相同的问题

That being said, the reason you mentioned ( The object is big and used often, I don't want to pass it in value type ) is not valid.话虽如此,您提到的原因(对象很大并且经常使用,我不想以值类型传递它)是无效的。

You won't pass your parameter as value if you remove ref .如果删除ref则不会将参数作为值传递 There won't be any performance/memory gain to use ref here.在这里使用ref不会有任何性能/内存增益。 See value vs reference .请参阅价值与参考

Instead:反而:

Thread recordThread = new Thread(() => RecordConversation(ref ChanResource));
recordThread.Start();

You should do:你应该做:

Thread recordThread = new Thread(() => {
    VoiceResource RecordResource = TServer.GetVoiceResource();
    RecordResource.MaximumTime = 6000;
    RecordResource.MaximumSilence = 6000;
    RecordResource.TerminationDigits = "";
});
recordThread.Start();

You don't have to pass this object as a reference if you are not recreating it in your method.如果您没有在方法中重新创建它,则不必将此对象作为引用传递。 If you are recreating it however than your ref would make sense:但是,如果您要重新创建它,那么您的 ref 就有意义:

public void RecordConversation(ref ChannelResource cr)
{
    cr = new ChannelResource();
    VoiceResource RecordResource = TServer.GetVoiceResource();
    RecordResource.MaximumTime = 6000;
    RecordResource.MaximumSilence = 6000;
    RecordResource.TerminationDigits = "";
}

Creating an object by ref causes the caller to be created as a new object.通过 ref 创建一个对象会导致调用者被创建为一个新对象。

You cannot send ref in lambda expressions because of the closure environment.由于关闭环境,您不能在 lambda 表达式中发送 ref 。 C# compiles the anonymous expressions in runtime. C# 在运行时编译匿名表达式。 If you try to send a ref to your closured code, then the compiler has to find a way to reach out your ref object which doesn't make sense.如果您尝试向关闭的代码发送 ref,那么编译器必须找到一种方法来访问您的 ref 对象,但这是没有意义的。 Here you can check the closures: http://en.wikipedia.org/wiki/Closure_(computer_science)在这里你可以查看闭包: http : //en.wikipedia.org/wiki/Closure_(computer_science)

public class ThreadParams
{
    public ChannelResource ChanResource;
    public ThreadParams(ChannelResource chanResource) {
        ChanResource = chanResource; }
}

public void ThreadProc(Object obj)
{
    RecordConversation(ref ((ThreadParams)obj).ChanResource);
}

Thread recordThread = new Thread(ThreadProc);
recordThread.Start(new ThreadParams(ChanResource));

The only problem is that your procedure now edits field inside passed object, not the actual variable, so you must check that field.唯一的问题是您的过程现在编辑传递对象内的字段,而不是实际变量,因此您必须检查该字段。

I'm not going to bother answering your question. 我不打算回答你的问题。 I will merely present some code that should help clarify matters in your head: 我只会提供一些有助于澄清问题的代码:

class Foo
{
    public string Bar{get;set;}
}

//somewhere else
void Main()
{
    var foo = new Foo();
    foo.Bar = "monkey";
    ChangeFoo(foo);
    //is it monkey or giraffe? 
    //according to your understanding, still monkey. Actually giraffe.
    Console.WriteLine(foo.Bar); 
}
void ChangeFoo(Foo someFoo)
{
    //someFoo is a reference to foo above, not a value copy
    foo.Bar = "giraffe";
}

I suggest you run this code, note the absence of any ref keyword, and consider its meaning in the context of your question, which is, frankly, a non-question. 我建议你运行这段代码,注意没有任何ref关键字,并在你的问题的上下文中考虑它的含义,坦率地说,这是一个非问题。 Hence my non-answer. 因此,我没有回答。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果“错误 CS1628:无法在匿名方法、lambda 或查询表达式中使用 in ref 或 out 参数”,如何在线程中使用 ref 参数? - How to use a ref parameter in a thread if "Error CS1628: Cannot use in ref or out parameter inside an anonymous method, lambda or query expression"? 为“ in”参数获取“无法在匿名方法,lambda表达式或查询表达式中使用ref或out参数” - Getting “Cannot use ref or out parameter inside an anonymous method, lambda expression, or query expression” for an “in” parameter 如何将“out”参数传递给 lambda 表达式 - How to pass 'out' parameter into lambda expression 如何将Generic Type参数传递给lambda表达式? - How to pass Generic Type parameter to lambda expression? 如何使用 EF 传递 Lambda 表达式作为方法参数 - How to pass a Lambda Expression as method parameter with EF 将lambda表达式作为参数传递,然后使用参数执行该lambda - Pass a lambda expression as a parameter, then execute that lambda with a parameter 将lambda表达式作为方法参数传递 - pass lambda expression as method parameter 如何通过lambda表达式“将任何数量的参数传递给方法”? - How to “pass in any number of arguments to the method” of a thread through lambda expression? 如何从Parallel.For或Parallel.ForEach lambda表达式访问ref或out参数 - how to access a ref or out parameter from Parallel.For or Parallel.ForEach lambda expression C#将Lambda表达式作为方法参数传递 - C# Pass Lambda Expression as Method Parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM