How to use ?? with lambda expression? - c#

Can we simplify the following with ?? and lambda expression?
Func<int, int> func = f; // f is a function parameter
if (func == null) // if f passed by the user is null then we use the default identity function f(x)=x.
func = x => x;
I cannot do something Func<int, int> func = f ?? x=>x;. Could you?
Edit
My scenario is as follows.
class Program
{
static double Average(int[] data, Func<int, int> f = null)
{
int sum = 0;
Func<int, int> func = f ?? new Func<int, int>(x => x);
//Func<int, int> func = f;
//if (func == null)
// func = x => x;
foreach (int x in data)
sum += func(x);
return (double)sum / data.Length;
}
static void Main(string[] args)
{
int[] data = { 1, 2, 3 };
Console.WriteLine(Average(data));
}
}

The precedence of null-coalescing operator is higher than lambda declaration.
Func<int, int> func = f ?? (x => x);

Possible duplicate of Null-coalescing operator and lambda expression
This should work
Func<int, int> func = f ?? (x=>x);
Your statement is parsed as
Func<int, int> func = (f ?? x)=>x;
Please search through the available answers first to check if somebody has already answered it.

Related

Set parameter of any Func<>

I have an object of any of the func types func<>, Func<,>, func<,,> ... And I'd like to replace one of the input parameters with a constant value.
eg:
object SetParameter<T>(object function, int index, T value){
//I don't know how to code this.
}
Func<int, String, String> function = (a, b) => a.ToString() + b;
object objectFunction = function;
object newFunction = SetParameter<int>(objectFunction, 0, 5);
// Here the new function should be a Func<String, String> which value "(b) => function(5, b)"
I already now how to get the type of the resulting function, but that does not really help me in implementing the desired behavior:
private Type GetNewFunctionType<T>(object originalFunction, int index, T value)
{
Type genericType = originalFunction.GetType();
if (genericType.IsGenericType)
{
var types = genericType.GetGenericArguments().ToList();
types.RemoveAt(index);
Type genericTypeDefinition = genericType.GetGenericTypeDefinition();
return genericTypeDefinition.MakeGenericType(types.ToArray());
}
throw new InvalidOperationException($"{nameof(originalFunction)} must be a generic type");
}
It's not quite clear what the purpose of your conversion is for, but wouldn't it be easier to avoid all the reflection. E.g.:
Func<int, string, string> func3 = (a, b) => a.ToString() + b;
Func<string, string> func3withConst = (b) => func3(10, b);
Since you are talking about a very limited scope (supporting just Func<TReturn>, Func<T1, TReturn> and Func<T1, T2, TReturn>) doing this through reflection is much more error prone and harder to read.
Just in case you need to use expression tree to build the function:
object SetParameter<T>(object function, int index, T value)
{
var parameterTypes = function.GetType().GetGenericArguments();
// Skip where i == index
var newFuncParameterTypes = parameterTypes.SkipWhile((_, i) => i == index).ToArray();
// Let's assume function is Fun<,,> to make this example simple :)
var newFuncType = typeof(Func<,>).MakeGenericType(newFuncParameterTypes);
// Now build a new function using expression tree.
var methodCallParameterTypes = parameterTypes.Reverse().Skip(1).Reverse().ToArray();
var methodCallParameters = methodCallParameterTypes.Select(
(t, i) => i == index
? (Expression)Expression.Constant(value, typeof(T))
: Expression.Parameter(t, "b")
).ToArray();
// func.Invoke(5, b)
var callFunction = Expression.Invoke(
Expression.Constant(function),
methodCallParameters);
// b => func.Invoke(5, b)
var newFunc = Expression.Lambda(
newFuncType,
callFunction,
methodCallParameters.OfType<ParameterExpression>()
).Compile();
return newFunc;
}
To use this:
Func<int, string, string> func = (a, b) => a.ToString() + b;
var newFunc = (Func<string, string>)SetParameter<int>(func, 0, 5);
// Output: 5b
Console.WriteLine(newFunc("b"));

Rewriting a ? operator with an if-else in c#

Can I write this
return (a, b) => (b == 0) ? 0: a / b;
With an if-else to the right of (a, b) =>
If you are returning a Func<double, double, double> it could be re-written as
return (a, b) =>
{
if(b == 0)
return 0;
else
return a / b;
};
If you are returning a Expression<Func<double, double, double>> it is not very easy to do, you will need to create a custom Expression by hand to represent the statement as there is no way to represent it in C#.
Have not tested it, but I think the Expression version would be
public Expression<Func<double, double, double>> IThinkThisWorks()
{
var paramA = Expression.Parameter(typeof(double), "a");
var paramB = Expression.Parameter(typeof(double), "b");
var const0 = Expression.Constant(0.0);
var test = Expression.Equal(paramA, paramB);
var division = Expression.Divide(paramA, paramB);
var ifCheck = Expression.IfThenElse(test, const0, division);
return Expression.Lambda<Func<double, double, double>>(ifCheck, paramA, paramB);
}

Is there any way to pass the lambda expression as a variable or argument?

I need to pass the lambda query as a parameter, the followings code is sample and I am interesting to find an implement for it, there is samples: some thing like this:
var expr1 = Where(n => n > 6).OrderBy(n => n % 2 == 0).Select(n => n);
var expr2 = TakeWhile((n, index) => n >= index));
And Use it Like this:
public void UseLambda<T> (IEnumerable<T> source , lambda Expr){
var items= Expr.Compile(source);
foreach(var item in items)
Console.Writeline(item.ToString());
}
public void Main(){
List<int> numbers = new List<int> { 10, 24, 9, 87, 193, 12, 7, 2, -45, -2, 9 };
var expr1 = Where(n => n > 6).OrderBy(n => n % 2 == 0).Select(n => n);
UseLambda(numbers, expr1);
}
Does any one have an idea about it?
Check Func(Of T, TResult) Delegate (MSDN)
using System;
public class LambdaExpression
{
public static void Main()
{
Func<string, string> convert = s => s.ToUpper();
string name = "Dakota";
Console.WriteLine(convert(name));
}
}
From MSDN
The underlying type of a lambda expression is one of the generic Func delegates. This makes it possible to pass a lambda expression as a parameter without explicitly assigning it to a delegate. In particular, because many methods of types in the System.Linq namespace have Func(Of T, TResult) parameters, you can pass these methods a lambda expression without explicitly instantiating a Func(Of T, TResult) delegate.
EDIT
Possible solution for your case
static void Main(string[] args)
{
List<int> numbers = new List<int> { 10, 24, 9, 87, 193, 12, 7, 2, -45, -2, 9 };
Func<IEnumerable<int>, IEnumerable<int>> expr = n => n.Where(n1 => n1 > 6).OrderBy(n1 => n1 % 2 == 0).Select(n1 => n1);
UseLambda<int>(numbers, expr);
}
private static void UseLambda<T>(List<T> numbers,
Func<IEnumerable<T>,
IEnumerable<T>> expr)
{
var values = expr(numbers);
foreach (var item in values) {
Console.WriteLine(item);
}
}
If you define your LINQ expressions like this:
Func<IEnumerable<int>, IEnumerable<int>> expr1 =
l => l.Where(n => n > 6).OrderBy(n => n % 2 == 0).Select(n => n);
Func<IEnumerable<int>, IEnumerable<int>> expr2 =
l => l.TakeWhile((n, index) => n >= index);
And your UseLambda method as:
public void UseLambda<T> (IEnumerable<T> source
,Func<IEnumerable<T>, IEnumerable<T>> lambda)
{
var items= lambda(source);
foreach(var item in items)
Console.Writeline(item.ToString());
}
}
Then you I think you have what you're looking for.
Do you mean something like this:
public void UseLambda<T> (IEnumerable<T> source , Func<T, bool> where, Func<T, bool> order)
{
if(source != null)
{
IOrderedEnumerable<T> orderBy = source.Where(where).OrderBy(order);
foreach (T value in orderBy)
{
Console.WriteLine(value);
}
}
}
So that you could call it like so:
UseLambda(numbers, x => x > 6, x => x % 2 == 0);
Well, a lambda is nothing but a delegate, so you could have a method like this:
public void DoIt(IEnumerable a, Action<IEnumerable> performThis)
{
performThis(a);
}
But where's the sense in it? Instead of calling a method that applies your lambda, why not calling it directly as you do in the last lines of your code?
public void UseLambda<T>(IEnumerable<T> source, Expression<Func<IEnumerable<T>, IEnumerable<T>>> expr)
{
var items = expr.Compile();
foreach (var item in items.Invoke(source))
{
Console.WriteLine(item.ToString());
}
}
public void Main()
{
Expression<Func<IEnumerable<int>, IEnumerable<int>>> expr = s => s.Where(n => n > 6).OrderBy(n => n % 2 == 0).Select(n => n);
var list = new List<int> { 10, 24, 9, 87, 193, 12, 7, 2, -45, -2, 9 };
UseLambda(list, expr);
}

a list of dynamic functions and dynamically calling them

I would like to be able to store various static methods in a List and later look them up and dynamically call them.
Each of the static methods has different numbers of args, types and return values
static int X(int,int)....
static string Y(int,int,string)
I'd like to have a List that I can add them all to:
List<dynamic> list
list.Add(X);
list.Add(Y);
and later:
dynamic result = list[0](1,2);
dynamic result2 = list[1](5,10,"hello")
How to do this in C# 4?
You can create a list of delegate-instances, using an appropriate delegate-type for each method.
var list = new List<dynamic>
{
new Func<int, int, int> (X),
new Func<int, int, string, string> (Y)
};
dynamic result = list[0](1, 2); // like X(1, 2)
dynamic result2 = list[1](5, 10, "hello") // like Y(5, 10, "hello")
You actually don't need the power of dynamic here, you can do with simple List<object>:
class Program
{
static int f(int x) { return x + 1; }
static void g(int x, int y) { Console.WriteLine("hallo"); }
static void Main(string[] args)
{
List<object> l = new List<object>();
l.Add((Func<int, int>)f);
l.Add((Action<int, int>)g);
int r = ((Func<int, int>)l[0])(5);
((Action<int, int>)l[1])(0, 0);
}
}
(well, you need a cast, but you need to somehow know the signature of each of the stored methods anyway)
List<dynamic> list = new List<dynamic>();
Action<int, int> myFunc = (int x, int y) => Console.WriteLine("{0}, {1}", x, y);
Action<int, int> myFunc2 = (int x, int y) => Console.WriteLine("{0}, {1}", x, y);
list.Add(myFunc);
list.Add(myFunc2);
(list[0])(5, 6);

Func<> delegate - Clarification

When an array is given:
int[] a={1,3,4,5,67,8,899,56,12,33}
and if i wish to return the even numbers using LINQ
var q=a.where(p=>p%2==0)
If i were to use C#2.0 and strictly func<> delegate what is the way to solve it?
I tried :
Func<int, bool> func = delegate(int val) { return val % 2 == 0; };
but I am confused how to link the array "a" here.
int[] q = Array.FindAll<int>(a, delegate(int p) { return p % 2 == 0; });
(note this uses Predicate<int>, which is the same signature as Func<int,bool>)
You can use Predicate and Array.FindAll.
Predicate<int> func = delegate(int val) { return val % 2 == 0; };
Array.FindAll<int>(a, func);

Categories

Resources