[英]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?如何解决?
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.但是
ref
和out
超出了范围,因此出现了错误。 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.