C#将Lambda表达式作为方法参数传递


105

我有一个lambda表达式,希望能够传递和重用。这是代码:

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>();   
  }   

这里的关键是,我希望能够将在此使用的lambda表达式传递到调用此代码的方法中,以便我可以重用它。lambda表达式是我的.Query方法中的第二个参数。我假设我想使用Action或Func,但是我不太确定此语法是什么或它如何工作。有人可以给我一个例子吗?


3
将参数设置为动作或函数。
蓝精灵都会(Metro Smurf)

是的,这就是我的想法。。。您可以举一个例子说明我该怎么做吗?
亚当·莱维特

Answers:


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方法的lambda?换句话说,在调用getJobs()之前,要定义lambda的那一行是什么?
亚当·莱维特

@AdamLevitt-与示例代码相同。将添加答案。
Oded

此外,功能参数是否仍可以是动态的?
亚当·莱维特

@AdamLevitt-您可以使函数通用,但是如果要在lambda上使用不同数量的参数,则将需要重载。
Oded

对。我真正想要的是能够传递IJob接口的不同实现,但这不适用于Dapper的Query <>,因为它在运行时需要实际的通用impl类。这仍然非常接近我的期望。
亚当·莱维特

27

据我了解,您需要以下代码。(通过参数传递表达式lambda)方法

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наđошƒаS

7

Lambda表达式的类型为Action<parameters>(如果不返回值)或Func<parameters,return>(如果具有返回值)。在您的情况下,您有两个输入参数,并且需要返回一个值,因此应使用:

Func<FullTimeJob, Student, FullTimeJob>

5

您应该使用委托类型并将其指定为命令参数。您可以使用内置的委托类型之一- ActionFunc

在您的情况下,您的委托看起来像有两个参数,并返回一个结果,因此您可以使用Func

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

然后,您可以GetJobs在委托实例中传递方法。这可能是匹配该签名,匿名委托或lambda表达式的方法。

PS:方法名称应使用PascalCase-而GetJobs不是getJobs

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.