Why can't you use a ref or out parameter in a lambda expression?
I came across the error today and found a workaround but I was still curious why this is a compile-time error.
CS1628: Cannot use in ref or out parameter 'parameter' inside an anonymous method, lambda expression, or query expression
Here's a simple example:
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
int newValue = array.Where(a => a == value).First();
}
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 a ref 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.
Under the hood, the anonymous method is implemented by hoisting captured variables (which is what your question body is all about) and storing them as fields of a compiler generated class. There is no way to store a ref or out parameter as a field. Eric Lippert discussed it in a blog entry. Note that there is a difference between captured variables and lambda parameters. You can have "formal parameters" like the following as they are not captured variables:
delegate void TestDelegate (out int x);
static void Main(string[] args)
{
TestDelegate testDel = (out int x) => { x = 10; };
int p;
testDel(out p);
Console.WriteLine(p);
}
You can but you must explicitly define all the types so
(a, b, c, ref d) => {...}
Is invalid, however
(int a, int b, int c, ref int d) => {...}
Is valid
As this is one of the top results for "C# lambda ref" on Google; I feel I need to expand on the above answers. The older (C# 2.0) anonymous delegate syntax works and it does support more complex signatures (as well closures). Lambda's and anonymous delegates at the very least have shared perceived implementation in the compiler backend (if they are not identical) - and most importantly, they support closures.
What I was trying to do when I did the search, to demonstrate the syntax:
public static ScanOperation<TToken> CreateScanOperation(
PrattTokenDefinition<TNode, TToken, TParser, TSelf> tokenDefinition)
{
var oldScanOperation = tokenDefinition.ScanOperation; // Closures still work.
return delegate(string text, ref int position, ref PositionInformation currentPosition)
{
var token = oldScanOperation(text, ref position, ref currentPosition);
if (token == null)
return null;
if (tokenDefinition.LeftDenotation != null)
token._led = tokenDefinition.LeftDenotation(token);
if (tokenDefinition.NullDenotation != null)
token._nud = tokenDefinition.NullDenotation(token);
token.Identifier = tokenDefinition.Identifier;
token.LeftBindingPower = tokenDefinition.LeftBindingPower;
token.OnInitialize();
return token;
};
}
Just keep in mind that Lambdas are procedurally and mathematically safer (because of the ref value promotion mentioned earlier): you might open a can of worms. Think carefully when using this syntax.
And maybe this?
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
var val = value;
int newValue = array.Where(a => a == val).First();
}
You can not use an out parameter directly in a lambda expression. The reason why you can not do that is explained in the other answers.
Workaround
But you can use a local temporary variable with for the inner function and, after the inner function has been executed, assign the out value from the inner function to the out value of the outer function:
private static int OuterFunc (int i_param1, out int o_param2)
{
int param2 = 0;
var del = () => InnerFunc (i_param1, out param2);
int result = del ();
o_param2 = param2;
return result;
}
private static int InnerFunc (int i_param1, out int o_param2)
{
o_param2 = i_param1;
return i_param1;
}
private static void Main (string[] args)
{
int result = OuterFunc (123, out int param2);
Console.WriteLine (result); // prints '123'
Console.WriteLine (param2); // prints '123'
}
Please note
The question was created in 2009. My answer was created in 2023 using C#10 and .NET 6. I don't know whether this answer had also worked back in 2009, which means, the code here might depend on enhancements to C# and .NET that might have been made in the meantime.
I will give you another example.
Description
The code below will throw out this error. Because the change brought by the lambda expression (i)=>{...} only works in the function test.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
Solution
So, if you remove out of the parameter, it works.
static void test(System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
If you need out really, don't change the parameter in the lambda expression directly. Instead, use a temporary variable please.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
System.Drawing.Image[] bitmapsTemp = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmapsTemp[i] = System.Drawing.Image.FromFile("2.bmp");
});
bitmaps = bitmapsTemp;
}
Related
I'm using C# 4.6.2, though could upgrade to 4.7.2 if it's possible there.
In many places in our code we have a loop with wait statements to check for a specific value when a function is called, wait and retry if it's not what we wanted until a maximum number of retries.
I'd like to abstract this out, but the only implementation I can think of requires you pass in a method with a variable number of arguments of variable types, which after much searching of Google appeared to not be possible about 5 years ago. There has been many improvements to C# since then, so
is it still not possible?
If it is now possible how do I do it?
If it isn't possible can you think of any other way I can achieve my goal?
The sort of thing I'm looking for is:
public bool GenericLoopWait(int maxWaitSeconds, int waitMsPerIteration,??? DoSomething,object expectedResult,...)
int maxRetries = maxWaitSeconds*1000/waitMsPerIteration;
SomeType result=null;
for(int i=0; i<maxRetries; i++){
result = DoSomething(...);
if(result==expectedResult) break;
Thread.Sleep(waitMsPerIteration);
}
return result==expectedResult
}
And then both of these would work:
GenericLoopWait(5,500,Browser.Webdriver.FindElements(selector).Any(),true);
GenericLoopWait(5,500,Api.GetSpecificObject(api,objectName),"expectedOutcome");
You could use generics and Func and wrap the actual calls parameters when you call through to the method.
public bool GenericLoopWait<T>(int maxWaitSeconds, int waitMsPerIteration, Func<T> DoSomething, T expectedResult = default(T))
{
int maxRetries = maxWaitSeconds * 1000 / waitMsPerIteration;
T result = default(T);
for (int i = 0; i < maxRetries; i++)
{
result = DoSomething();
if (expectedResult.Equals(result)) break;
Thread.Sleep(waitMsPerIteration);
}
return expectedResult.Equals(result);
}
Calling code:
GenericLoopWait(5, 500, () => Browser.Webdriver.FindElements(selector).Any(), true);
GenericLoopWait(5, 500, () => Api.GetSpecificObject(api,objectName), "expectedOutcome")
Working dotnetfiddle
The general pattern is to create a "Wrapper" method that accepts an Action or a Func as a parameter. Your wrapper can do it's own logic, and Invoke the parameter at the correct time.
As a simple generic example:
public void MethodWrapper(Action action)
{
Console.WriteLine("begin");
action.Invoke();
Console.WriteLine("end");
}
You could then do this:
void Main()
{
var a = 1;
var b = 2;
MethodWrapper(() => DoSomething(a));
MethodWrapper(() => DoSomethingElse(a,b));
}
public void DoSomething(int a)
{
Debug.WriteLine($"a={a}");
}
public void DoSomethingElse(int a, int b)
{
Debug.WriteLine($"a={a}, b={b}");
}
To generate this output:
begin
a=1
end
begin
a=1, b=2
end
For your specific case, your wrapper could take additional parameters specifying things like number of retries, time between calls, or acceptance criteria.
I am curious as to what is the point of creating instances of delegates. I understand that they are function pointers but what is the purpose of the using delegate instances?
public delegate bool IsEven(int x);
class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { 1, 3, 4, 5, 6,7, 8, 9 };
// creating an instance of delegate and making it point to 'CheckEven' function
IsEven isEven = new IsEven(CheckEven);
// using delegate for parameter to get sum of evens
int tot1 = Sums(nums, isEven);
// passing in the function directly as parameter and not delegate instance
int tot2 = Sums(nums, CheckEven);
// using lambda expressions
int tot3 = Sums(nums, x=> x%2==0);
ReadKey();
}
public static int Sums(int[] nums, IsEven isEvenOdd)
{
int sum = 0;
foreach(int x in nums)
{
if (isEvenOdd(x))
sum += x;
}
return sum;
}
public static bool CheckEven(int x)
{
if (x % 2 == 0)
return true;
else
return false;
}
}
At first thought opting to always use lambdas seems like the best idea if the functionality of the function you are going to pass does not have complex implementation, otherwise why wouldn't I just pass my function directly into the parameters? Also with Lambdas it is much easier to change it to compute the sum of odds as oppose to creating an entire new method as I would have to with delegates.
You already used delegates even if you passed the method directly, the Sums method could not receive the method name if it's not set its expectation by the delegate definition.
Consider changing the delegate name to public delegate bool EvenOddStatus(int x);
you can send either your CheckEven method or this method:
public static bool CheckOdd(int x)
{
if (x % 2 != 0) // here changed
return true;
else return false;
}
(of course you can use lambda here, but not in more complicated scenarios)
Now your Sums method can sum up either odd or even numbers based on the calling code (either pass CheckEven or CheckOdd).
Delegates are pointers to methods. you define how the code want the method to receive and return, and the calling code can pass a pre-defined implementation later, either a method or delegate.
What if your Main is another method that doesn't know what to sum, odds or evens? it will have a delegate from a calling code up the stack.
Is there a way to create c++ style pointer in c#? I need this to set an int in several places when I don't know which int it is.
Like in c++ I would do:
int *i;
if(cond0) i = &someint;
if(cond1) i = &otherint;
if(cond2) i = &thirdint;
if(cond3) *i = someval;
if(cond4) *i = otherval;
if(cond5) *i = thirdval;
If I do this in c# style I will need 9 ifs and my program has much more conditions so its not feasible.
I thought of make some sort of value like:
int val;
if(cond3) val = someval;
if(cond4) val = otherval;
if(cond5) val = thirdval;
if(cond0) someint = val;
if(cond1) otherint = val;
if(cond2) thirdint = val;
but it's not possible because cond3, 4 and 5 are scattered along the program.
It is, but you have to wrap any code that does it in an unsafe block.
Alternatively, if this is happening in a method then you might be able to use the 'ref' keyword to pass a parameter in by reference.
Both of these options really constrain the solution to method boundaries. If you're dealing with anything more scattered than that, in C# it's probably better to try and find ways to reorganize your code to use less global state instead.
Yes, there is a type called IntPtr which I use for Windows handles.
Here's an example of C# pointers that illustrates both their declaration and how to wrap them in an unsafe block
Also, see the C# Programming Guide - Pointer Types
I'm not sure if you provided enough information in your question to give a correct answer, but one possible solution is to set the values in a function using ref parameters.
class Program
{
static void Main(string[] args)
{
var i = 1;
var someint = 2;
var otherint = 3;
var thirdint = 4;
Console.WriteLine("i: {0}\nsomeint: {1}\notherint: {2}\nthirdint: {3}", i, someint, otherint, thirdint);
SetInts(true, false, false, false, false, false, ref i, ref someint, ref otherint, ref thirdint);
Console.WriteLine("i: {0}\nsomeint: {1}\notherint: {2}\nthirdint: {3}", i, someint, otherint, thirdint);
Console.ReadKey();
}
static void SetInts(bool cond0, bool cond1, bool cond2, bool cond3, bool cond4, bool cond5, ref int i, ref int someint, ref int otherint, ref int thirdint)
{
if (cond0) i = someint;
if (cond1) i = otherint;
if (cond2) i = thirdint;
if (cond3) i = someint;
if (cond4) i = otherint;
if (cond5) i = thirdint;
}
}
I wonder if there's any way something like this would be possible for value types...
public static class ExtensionMethods {
public static void SetTo(this Boolean source, params Boolean[] bools) {
for (int i = 0; i < bools.Length; i++) {
bools[i] = source;
}
}
}
then this would be possible:
Boolean a = true, b, c = true, d = true, e;
b.SetTo(a, c, d, e);
Of course, this does not work because the bools are a value type so they are passed into the function as a value, not as a reference.
Other than wrapping the value types into reference types (by creating another class), is there any way to pass a variable into function by the reference (ref) while using params modifier?
This is not possible. To explain why, first read my essay on why it is that we optimize deallocation of local variables of value type by putting them on the stack:
https://web.archive.org/web/20100224071314/http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx
Now that you understand that, it should be clear why you cannot store a "ref bool" in an array. If you could, then you could have an array which survives longer than the stack variable being referenced. We have two choices: either allow this, and produce programs which crash and die horribly if you get it wrong -- this is the choice made by the designers of C. Or, disallow it, and have a system which is less flexible but more safe. We chose the latter.
But let's think about this a little deeper. If what you want is to pass around "thing which allows me to set a variable", we have that. That's just a delegate:
static void DoStuff<T>(this T thing, params Action<T>[] actions)
{
foreach(var action in actions) action(thing);
}
...
bool b = whatever;
b.DoStuff(x=>{q = x;}, x=>{r = x;} );
Make sense?
There isn't really a way. You could do something like this:
public static void Main(string[] args)
{
BooleanWrapper a = true, b = true, c = true, d = true, e = new BooleanWrapper();
b.SetTo(a, c, d, e);
}
public static void SetTo(this BooleanWrapper sourceWrapper, params BooleanWrapper[] wrappers)
{
foreach (var w in wrappers)
w.Value = sourceWrapper.Value;
}
public class BooleanWrapper
{
public BooleanWrapper() { }
public BooleanWrapper(Boolean value)
{
Value = value;
}
public Boolean Value { get; set; }
public static implicit operator BooleanWrapper(Boolean value)
{
return new BooleanWrapper(value);
}
}
But then again how is that any better than just doing this:
public static void Main(string[] args)
{
Boolean[] bools = new Boolean[5];
bools.SetTo(bools[1]); // Note I changed the order of arguments. I think this makes more sense.
}
public static void SetTo(this Boolean[] bools, Boolean value)
{
for(int i = 0; i < bools.Length; i++)
bools[i] = value;
}
After all, an array is a sequence of variables. If you need something that behaves like a sequence of variables, use an array.
Unfortunately the community of Java, and now .NET, developers decided that less flexibility in the name of "safety" is the preferred solution, and to achieve the same result with less lines of code you have to opt for extraordinary complexity (all those class structures, delegates, etc.).
In Delphi I could simply do something like this:
var
a: integer; f: double; n: integer;
sscanf(fmtstr, valuestr, [#a, #f, #n]);
//<-- "sscanf" is a function I wrote myself that takes an open array of pointers.
In C# You would have to do:
int a; double f; int n;
object [] o = new object[];
sscanf(fmtstr, valuestr, ref o);
a = o[0];
f = o[1];
n = o[2];
That's 5 lines of code to do what I could do in 1 line of Delphi code. I think there is a formula somewhere that the likelihood of bugs in code increases geometrically with the number of lines of code; so if you have 20 lines of code you're code is 4 times more likely to have bugs than if you have 10.
Of course, you can decrease your # lines of code by using the delegate with all those weird angle brackets and strange syntax, but I would think that's also a haven for bugs.
Here is some interesting solution:
public delegate RecursionRefFunc<T> RecursionRefFunc<T>(ref T arg);
public static RecursionRefFunc<T> Boo<T>(ref T input)
{
Console.WriteLine(input); // Work in here
return Boo;
}
public static void Main(string[] args)
{
int x1 = 1, x2 = 2, x3 = 3, x4 = 4, x5 = 5;
Boo(ref x1)(ref x2)(ref x3)(ref x4)(ref x5);
}
// Output: //
// 1
// 2
// 3
// 4
// 5
Delegate can declare in recursion.
Return a function outside and call again.
And you will be killed by the code reviewer.
Advertisement OW<: CWKSC/MyLib_Csharp
This would not be possible even if bools were reference types. While a class is a reference type, the variable in the Boolean[] is still a value, it's just that the value is a reference. Assigning the value of the reference just changes the value of that particular variable. The concept of an array of ref variables doesn't make sense (as arrays are, by their nature, a series of values).
I'm trying to convert a proprietary string mask to the .net equivalent of it.
For that I need to exchange every occurance of [someText] with {aDigit}.
private static int hits = 0;
private static object hitsLock = new object();
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString) {
Regex bracketsExpression = new Regex(#"\[[^[]*]");
lock (hitsLock)
{
hits = 0;
return bracketsExpression.Replace(sdsFileMaskString, ReplaceSquareWithAngularBrackets);
}
}
private static string ReplaceSquareWithAngularBrackets(Match m) {
string result = String.Format("{{{0}}}", hits.ToString());
hits++;
return result;
}
It works. But both expressions need to know each other's workings and are depending on the hits counter. I feel this could be improved. Ideally both have no dependency on each other. Any suggestions?
This can probably be done better. Any suggestions?
Yes - use an anonymous method or lambda expression:
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString)
{
Regex bracketsExpression = new Regex(#"\[[^[]*]");
int hits = 0;
return bracketsExpression.Replace(sdsFileMaskString, match =>
{
string result = String.Format("{{{0}}}", hits.ToString());
hits++;
return result;
});
}
This will capture the local variable in a new (compiler-generated) type, getting rid of the "globalness".
If you're happy with side-effects, you could make the lambda expression simpler, too. I'd also get rid of the call to String.Format in this case, as all those braces are confusing:
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString)
{
Regex bracketsExpression = new Regex(#"\[[^[]*]");
int hits = 0;
return bracketsExpression.Replace(sdsFileMaskString,
match => "{" + (hits++) + "}");
}
By using a lambda, and a local variable hits, C# will create a closure :
public static string ConvertSdsFileMaskToStringMask(string sdsFileMaskString)
{
Regex bracketsExpression = new Regex(#"\[[^[]*]");
int hits = 0;
return bracketsExpression.Replace(sdsFileMaskString,
m => string.Format("{{{0}}}", hits++));
}
will be sufficient
The hits variable is encapsulated in the lambda closure and will be reused inside all lambda calls, but will be distinct for several ConvertSdsFileMaskToStringMask calls.