C # Передача лямбда-експресії як параметр методу


105

У мене є лямбда-вираз, який я хотів би мати можливість пройти навколо та повторно використовувати. Ось код:

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
Зробіть параметр дія або функція.
Метро Смурф

Правильно, ось що я подумав ... чи можете ви показати мені приклад того, як я це зробив?
Адам Левітт

Відповіді:


122

Використовуйте 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 - Так само, як і у прикладі коду. Додамо у відповідь.
Одід

Також, чи можуть параметри функції в будь-якому разі бути динамічними?
Адам Левітт

@AdamLevitt - ви можете зробити функцію загальною, хоча якщо вам потрібні різні параметри на лямбдах, вам знадобляться перевантаження.
Oded

Правильно. Що я насправді хотів би - це можливість передати різні реалізації інтерфейсу IJob, але це не працюватиме з запитом Dapper <>, тому що він вимагає фактичного загального класу 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? Я бачив, що це працює і без цього.
Snađошƒаӽ

7

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

Func<FullTimeJob, Student, FullTimeJob>

5

Вам слід використовувати тип делегата і вказати це як ваш параметр команди. Ви можете використовувати один із вбудованих типів делегатів - Actionі Func.

У вашому випадку, схоже, ваш делегат приймає два параметри і повертає результат, щоб ви могли використовувати Func:

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

Потім ви можете викликати свій GetJobsметод, передаючи в екземпляр делегата. Це може бути метод, який відповідає цьому підпису, анонімного делегата або лямбда-виразу.

PS Ви повинні використовувати PascalCase для імен методів - GetJobs, ні getJobs.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.