C # Передача лямбда-выражения в качестве параметра метода

106

У меня есть лямбда-выражение, которое я хотел бы передавать и использовать повторно. Вот код:

public List<IJob> getJobs(/* i want to pass the lambda expr in here */) {
  using (SqlConnection connection = new SqlConnection(getConnectionString())) {
    connection.Open();
    return connection.Query<FullTimeJob, Student, FullTimeJob>(sql, 
      (job, student) => {         
        job.Student = student;
        job.StudentId = student.Id;
        return job;
        },
        splitOn: "user_id",
        param: parameters).ToList<IJob>();   
  }   

Ключевым моментом здесь является то, что я хочу иметь возможность передавать лямбда-выражение, которое я использую здесь, в метод, вызывающий этот код, чтобы я мог повторно использовать его. Лямбда-выражение - второй аргумент внутри моего метода .Query. Я предполагаю, что хочу использовать Action или Func, но я не совсем уверен, каков синтаксис для этого и как он работает. Кто-нибудь может привести мне пример?

Адам Левитт
источник
3
Сделайте параметр Action или Func.
Metro Smurf
Хорошо, вот что я подумал ... можешь показать мне пример, как я это сделаю?
Адам Левитт
возможный дубликат лямбда-выражений C # в качестве аргументов функции
пользователь

Ответы:

123

Используйте Func<T1, T2, TResult>делегат в качестве типа параметра и передайте его в свой Query:

public List<IJob> getJobs(Func<FullTimeJob, Student, FullTimeJob> lambda)
{
  using (SqlConnection connection = new SqlConnection(getConnectionString())) {
    connection.Open();
    return connection.Query<FullTimeJob, Student, FullTimeJob>(sql, 
        lambda,
        splitOn: "user_id",
        param: parameters).ToList<IJob>();   
  }  
}

Вы бы назвали это:

getJobs((job, student) => {         
        job.Student = student;
        job.StudentId = student.Id;
        return job;
        });

Или назначьте лямбду переменной и передайте ее .

Одед
источник
Это выглядит очень хорошо, и как мне определить лямбда ВНЕ этого метода getJobs? Другими словами, как выглядит строка перед вызовом getJobs () для определения лямбда?
Адам Левитт
@AdamLevitt - так же, как и в вашем примере кода. Добавлю в ответ.
Oded
Кроме того, могут ли параметры функции быть динамическими?
Адам Левитт
@AdamLevitt - вы можете сделать функцию универсальной, хотя, если вам нужно другое количество параметров в лямбдах, вам потребуются перегрузки.
Oded
Правильно. На самом деле я бы хотел иметь возможность передавать различные реализации интерфейса IJob, но это не будет работать с Dapper Query <>, потому что во время выполнения требуется фактический общий класс impl. Это все еще довольно близко к тому, на что я надеялся.
Адам Левитт
27

Если я понимаю, вам нужен следующий код. (передача выражения лямбда по параметру) Метод

public static void Method(Expression<Func<int, bool>> predicate) { 
    int[] number={1,2,3,4,5,6,7,8,9,10};
    var newList = from x in number
                  .Where(predicate.Compile()) //here compile your clausuly
                  select x;
                newList.ToList();//return a new list
    }

Метод вызова

Method(v => v.Equals(1));

Вы можете сделать то же самое в их классе, см. Это пример.

public string Name {get;set;}

public static List<Class> GetList(Expression<Func<Class, bool>> predicate)
    {
        List<Class> c = new List<Class>();
        c.Add(new Class("name1"));
        c.Add(new Class("name2"));

        var f = from g in c.
                Where (predicate.Compile())
                select g;
        f.ToList();

       return f;
    }

Метод вызова

Class.GetList(c=>c.Name=="yourname");

Я надеюсь это будет полезно

Маринпьетри
источник
2
Вы можете объяснить, зачем нам нужен Compile()в .Where? Я видел, как это работает и без этого.
Sнаđошƒаӽ
7

Лямбда-выражения имеют тип Action<parameters>(в случае, если они не возвращают значение) или Func<parameters,return>(в случае, если они имеют возвращаемое значение). В вашем случае у вас есть два входных параметра, и вам нужно вернуть значение, поэтому вы должны использовать:

Func<FullTimeJob, Student, FullTimeJob>
SztupY
источник
5

Вы должны использовать тип делегата и указать его в качестве параметра команды. Вы можете использовать один из встроенных типов делегатов - Actionи Func.

В вашем случае похоже, что ваш делегат принимает два параметра и возвращает результат, поэтому вы можете использовать Func:

List<IJob> GetJobs(Func<FullTimeJob, Student, FullTimeJob> projection)

Затем вы можете вызвать свой GetJobsметод, передав экземпляр делегата. Это может быть метод, соответствующий этой сигнатуре, анонимный делегат или лямбда-выражение.

PS Вы должны использовать PascalCase для имен методов - GetJobsне getJobs.

devdigital
источник