Cannot use ref or out parameter in lambda expressions
Lambdas have the appearance of changing the lifetime of variables that they capture. For instance, the following lambda expression causes the parameter p1 to live longer than the current method frame as its value can be accessed after the method frame is no longer on the stack
Func<int> Example(int p1) {
return () => p1;
}
Another property of captured variables is that changes to the variables are also visible outside the lambda expression. For example, the following code prints out 42
void Example2(int p1) {
Action del = () => { p1 = 42; };
del();
Console.WriteLine(p1);
}
These two properties produce a certain set of effects which fly in the face of a ref
parameter in the following ways:
ref
parameters may have a fixed lifetime. Consider passing a local variable as aref
parameter to a function.- Side effects in the lambda would need to be visible on the
ref
parameter itself. Both within the method and in the caller.
These are somewhat incompatible properties and are one of the reasons they are disallowed in lambda expressions.
Cannot use ref or out parameter inside an anonymous method
Well, you're not allowed to use a ref
or a out
parameter in an anonymous method or a lambda, just as the compiler error says.
Instead you have to copy the value out of the ref
parameter into a local variable and use that:
var nodeId = c.NodeID;
var coordinates = from r in xdoc.Descendants("move")
where int.Parse(r.Attribute("id").Value) == nodeId
...
How to pass 'out' parameter into lambda expression
As the compiler error indicates, it isn't allowed to use out or ref parameters inside lambda expressions.
Why not just use a copy? It's not like the lambda wants to mutate the variable anyway, so I don't see a downside.
string prettyNameCopy = prettyName;
var matchingProperties = getLocalProperties()
.Where(prop => prop.Name == prettyNameCopy);
Alternatively, you can use a local throughout (to evaluate the appropriate name etc.), and assign the out
parameter prettyName
just before returning from the method. This will probably be more readable if there isn't significant branching within the method.
Getting Cannot use ref or out parameter inside an anonymous method, lambda expression, or query expression for an in parameter
Behind the scenes, in
is a ref
parameter, but with fancy semantics. The same as out
is a ref
parameter with fancy semantics. The compiler message could be clearer, perhaps - that might be a good bug to log on the Roslyn github. But: it is correct to error. I would agree that the error should explicitly mention in
parameters.
How to pass a ref parameter inside lambda expression? - Thread issue
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.
Cannot use use ref or out parameter for anonymous methods
I would recommend sharing strClientId
as static variable:
static BackgroundWorker worker;
static string strClientId;
static void Main(string[] args)
{
worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerAsync();
Console.ReadLine();
}
static void worker_DoWork(object sender,DoWorkEventArgs e)
{
strClientId = "2211";
Authenticate();
}
static void Authenticate()
{
Timer timer = new Timer(500);
timer.Elapsed += (sender, e) => Authenticates_Timer(sender, e);
timer.Start();
}
static void Authenticates_Timer(object sender, ElapsedEventArgs e)
{
strClientId = "";
}
Will it work for you?
Update: Ok, let's try this one:
static void worker_DoWork(object sender,DoWorkEventArgs e)
{
string strClientId = "";
var setClientId = new Action<string>(v => { strClientId = v; });
setClientId("2211");
Authenticate(setClientId);
}
static void Authenticate(Action<string> setClientId)
{
Timer timer = new Timer(500);
timer.Elapsed += (sender, e) => Authenticates_Timer(sender, e, setClientId);
timer.Start();
}
static void Authenticates_Timer(object sender, ElapsedEventArgs e, Action<string> setClientId)
{
setClientId("");
}
Out variables and nested lambdas
For why you can't use ref
/out
parameters, see this post.
You seem to want to recreate a "loop" statement with a "break" functionality. Rather than using out
parameters to implement the break
statement, you can use another Action<bool>
delegate instead.
public class Loop
{
protected Action<Action<bool>> action;
public Loop Infinite(Action<Action<bool>> actn)
{
action = actn;
Start();
return this;
}
protected void Start()
{
bool exit = false;
while (!exit)
{
// passes the Action<bool> that assigns the given bool to exit
action((b) => exit = b);
}
}
}
int outer = 0;
Loop l1 = new Loop().Infinite(setOuterExit =>
{
int inner = 0;
outer++;
Loop l2 = new Loop().Infinite(setInnerExit =>
{
inner++;
Console.WriteLine($"{outer}-{inner}");
setInnerExit(inner >= 3);
setOuterExit(inner >= 3);
});
setOuterExit(outer >= 3);
});
This gives a final outer
value of 3. But if you wanted that, you could have just removed the setOuterExit
call in the inner loop - it also gives 3 as output.
Right now the value assigned to exit
by the inner setOuterExit
call is being "overwritten" by the outer setOuterExit
call, so the outer loop doesn't break immediately when it hits the inner setOuterExit
. We could change the assignment to exit
to:
action((b) => exit |= b);
So that if exit
is ever set to true
, no other values can overwrite it. This will solve this problem, but note that setOuterExit
still won't work the same as a real break;
statement. The code immediately after setOuterExit
still gets executed, for example.
Cannot setup the function with out parameter using lambda expression
This might work for you:
//define the callback delegate
delegate void TryGetCallback(CompositeKey key, out string str, Func<CompositeKey, string> func);
mock.Setup(x => x.TryGet(
It.IsAny<CompositeKey>(),
out It.Ref<string>.IsAny,
It.IsAny<Func<CompositeKey, string>>()))
.Callback(new TryGetCallback((CompositeKey key, out string str, Func<CompositeKey, string> func) =>
{
str = "foo bar";
}))
.Returns(true);
with such a setup you could archive what you want
string actualValue;
bool result = mock.Object.TryGet(new CompositeKey(), out actualValue)
//actualValue = "foo bar", result = true
Related Topics
Richtextbox Syntax Highlighting in Real Time--Disabling the Repaint
How to Download HTML Source in C#
Handling Warning for Possible Multiple Enumeration of Ienumerable
Compare Using Thread.Sleep and Timer for Delayed Execution
Shouldserialize*() VS *Specified Conditional Serialization Pattern
Tolist()-- Does It Create a New List
Why Implement Interface Explicitly
How to Force Https Using a Web.Config File
Reading File Input from a Multipart/Form-Data Post
How to Convert JSON Text into Objects Using C#
In Unity (C#), Why am I Getting a Nullreferenceexception and How to Fix It
How to Determine Programmatically Whether a Particular Process Is 32-Bit or 64-Bit
Displayname Attribute from Resources
Wpf Webbrowser Control - How to Suppress Script Errors
Gradient Circles for Map Generator
Populating a Razor Dropdownlist from a List<Object> in MVC