This question already has answers here:
Can a Delegate have an optional parameter?
(2 answers)
Closed 9 years ago.
Why this piece of code does not compile?
delegate int xxx(bool x = true);
xxx test = f;
int f()
{
return 4;
}
Optional parameters are for use on the calling side - not on what is effectively like a single-method-interface implementation. So for example, this should compile:
delegate void SimpleDelegate(bool x = true);
static void Main()
{
SimpleDelegate x = Foo;
x(); // Will print "True"
}
static void Foo(bool y)
{
Console.WriteLine(y);
}
What will happen test(false)? It will corrupt the stack, because signatures must match.
Try this way:
static int f(bool a)
{
return 4;
}
Related
This question already has answers here:
Cleanest way to write retry logic?
(30 answers)
Closed 2 years ago.
I wish to create an extension method that takes A function with a parameter of IEnumerable<T>.
int NumberOfRetries = 3;
string TableName = "Table";
Method(EnumerableParameter).RetrySection(EnumerableParameter,TableName ,NumberOfRetries);
Function to be extended
bool Method(IEnumerable<int> param)
{
foreach(var item in param)
{
Console.WriteLine(item);
}
return true;
}
I am having difficulty making the code compile
RetrySection(() => Method(EnumerableParameter),EnumerableParameter,TableName ,NumberOfRetries);
for both options.
Method(EnumerableParameter).RetrySection(EnumerableParameter,TableName,NumberOfRetries);
Extension Method
public static void RetrySection(this Func<IEnumerable<T>,bool> action, IEnumerable<T> parameter,string databaseTable,int jobcount)
{
int jobRowCount = ValidateTable(databaseTable).GetAwaiter().GetResult();
int retry = 0;
do
{
action(parameter);
jobRowCount = ValidateTable(databaseTable).GetAwaiter().GetResult();
retry++;
}
while ((jobRowCount < (jobcount * 2)) && retry < 3);
}
I'm getting the error Func<IEnumerable<int>,bool> does not take 0 arguments.
The solution is to use:
Method.RetrySection(EnumerableParameter,TableName ,NumberOfRetries);
because that is what RetrySection is defined to work on - Func<IEnumerable,bool>, instead of the result - bool.
Or, in case of the second example:
RetrySection(Method,EnumerableParameter,TableName ,NumberOfRetries);
This question already has answers here:
get name of a variable or parameter [duplicate]
(3 answers)
What is the purpose of nameof?
(17 answers)
Closed 4 years ago.
I have a parameter d. I want to use the name of the parameter in an error message:
void foo(string d)
{
// this does not work
string message string.Format("Parameter {0} is missing please verify inputs", d));
}
How can I get the name of a parameter?
You can use nameof:
string nameOfD = nameof(d);
Note that this will not give the name of the variables used to call a method, it just works for the local variable. In this case, nameof will always return "d".
You can use Lambda expressions:
static void Main( string[] args ) {
int A = 50, B = 30, C = 17;
Print( () => A );
Print( () => B );
Print( () => C );
}
static void Print<T>( System.Linq.Expressions.Expression<Func<T>> input ) {
System.Linq.Expressions.LambdaExpression lambda = (System.Linq.Expressions.LambdaExpression)input;
System.Linq.Expressions.MemberExpression member = (System.Linq.Expressions.MemberExpression)lambda.Body;
var result = input.Compile()();
Console.WriteLine( "{0}: {1}", member.Member.Name, result );
}
Try this one.
You could use a concatenation of String.IsNullOrEmpty(variable)?nameof(variable):String.Empty. So you'd get
var str = String.Join(',', new List<String>
{
String.IsNullOrEmpty(a)?nameof(a):String.Empty,
String.IsNullOrEmpty(b)?nameof(b):String.Empty,
String.IsNullOrEmpty(c)?nameof(c):String.Empty,
String.IsNullOrEmpty(d)?nameof(d):String.Empty
});
string.Format("Parameter {0} is missing please verify inputs", str);
This question already has answers here:
C#: Recursive functions with Lambdas
(3 answers)
Closed 9 years ago.
How can you call a Func function from itself?
For example:
Func<int, int> f = x => {
// do stuff
if (x > 5) { return f(x); }
// do other stuff
};
Simple way to is to create the variable, assign it null, and then use it in your lambda:
Func<int, int> f = null;
f = x => {
// do stuff
if (x > 5) { return f(x); }
// do other stuff
};
By the time it comes to actually invoke the delegate in f, it will have been assigned to a non-null value.
If you prefer, you can also follow the approach shown in this (theory heavy) blog entry.
dlev's answer is fairly straight forward, but you can also do this way:
First declare a delegate type that accepts itself as a parameter:
public delegate TResult RecursiveFunc<TParam, TResult>(
TParam param1,
RecursiveFunc<TParam, TResult> func);
NOTE: of course the delegate doesn't have to be generic.
You can now create your lambda expression like this:
RecursiveFunc<int, int> f = (x, g) => {
// do stuff
if (x > 5) { return g(x, g); }
// do other stuff
};
f(123, f); // Invoke recursively
This question already has answers here:
When to use in vs ref vs out
(17 answers)
Closed 9 years ago.
When should we actually use ref and out.
I know the difference between the two.
Before you can pass a ref parameter, you must assign it to a value. which is not compulsory in out.
But when should we use ref. ??
I read this, but didnt got, when should I use ref.
http://www.dotnetperls.com/ref
Here is an example:
static void Main(string[] args)
{
int i = 1;
foo(i);
Console.Write(i); //i=1;
Reffoo(ref i);
Console.Write(i); //i=2;
}
static void Reffoo(ref int i)
{
i++;
}
static void foo(int i)
{
i++;
}
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;
}