Есть ли способ передать лямбда-выражение как переменную или аргумент?
Мне нужно передать лямбда-запрос в качестве параметра, следующий код - образец, и мне интересно найти для него реализацию, есть примеры: что-то вроде этого:
var expr1 = Where(n => n > 6).OrderBy(n => n % 2 == 0).Select(n => n);
var expr2 = TakeWhile((n, index) => n >= index));
И использовать его:
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);
}
Есть ли у кого-нибудь идеи об этом?
Ответы
Ответ 1
Если вы определяете выражения LINQ следующим образом:
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);
И ваш метод UseLambda как:
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());
}
}
Тогда вы, я думаю, у вас есть то, что вы ищете.
Ответ 2
Отметьте делегат Func (Of T, TResult) (MSDN)
using System;
public class LambdaExpression
{
public static void Main()
{
Func<string, string> convert = s => s.ToUpper();
string name = "Dakota";
Console.WriteLine(convert(name));
}
}
Из MSDN
Основной тип выражения лямбда - это один из общих Func делегатов. Это позволяет передавать лямбда-выражение в качестве параметра без явного назначения его делегату. В частности, поскольку многие методы типов в пространстве имен System.Linq имеют параметры Func (Of T, TResult), вы можете передать этим методам лямбда-выражение без явного создания экземпляра Func (Of T, TResult).
ИЗМЕНИТЬ
Возможное решение для вашего случая
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);
}
}
Ответ 3
Вы имеете в виду что-то вроде этого:
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);
}
}
}
Чтобы вы могли называть его так:
UseLambda(numbers, x => x > 6, x => x % 2 == 0);
Ответ 4
Ну, лямбда - не что иное, как делегат, поэтому у вас может быть такой метод:
public void DoIt(IEnumerable a, Action<IEnumerable> performThis)
{
performThis(a);
}
Но где смысл в нем? Вместо вызова метода, который применяет ваш лямбда, почему бы не вызвать его напрямую, как в последних строках вашего кода?
Ответ 5
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);
}