2

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

How to fix it?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104

5 Answers5

4

Why that error?

The scope of the parameters of an anonymous method is the anonymous-method-block.

(Emphasis mine)

lambda expressions are essentially the same as anonymous method.

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. 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.

You can modify the parameter directly to reflect that change.

Amit Joki
  • 58,320
  • 7
  • 77
  • 95
2

You can't use 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. There won't be any performance/memory gain to use ref here. See value vs reference.

Community
  • 1
  • 1
ken2k
  • 48,145
  • 10
  • 116
  • 176
  • But I am confused, if the object is used 10 times and we pass it in value 10 times. Is there a memory issue? –  May 05 '14 at 16:08
  • @Love There isn't any memory issue. Without `ref`, what will happen is that the _reference_ of your object will be passed as value, not the object itself. – ken2k May 05 '14 at 16:12
  • --@ken2k, the reason I use ref ifs from an answer from http://stackoverflow.com/questions/4986341/where-should-i-prefer-pass-by-reference-or-pass-by-value. 2.If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit. –  May 05 '14 at 16:18
  • 2
    @Love That's a C++ answer. How memory is managed between C++ and .Net (C#) is really, really different. – ken2k May 05 '14 at 16:22
  • @Love Keep in mind that the "copy" only exists in memory for the scope of the function. Once the function is finished then the copy is destroyed and returned to memory. – Smeegs May 05 '14 at 17:00
0

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();
Dzior
  • 1,485
  • 1
  • 14
  • 30
0

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:

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.

You cannot send ref in lambda expressions because of the closure environment. C# compiles the anonymous expressions in runtime. 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. Here you can check the closures: http://en.wikipedia.org/wiki/Closure_(computer_science)

Bura Chuhadar
  • 3,653
  • 1
  • 14
  • 17
0
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.

Elvedin Hamzagic
  • 825
  • 1
  • 9
  • 22