C # Lambda-Ausdruck als Methodenparameter übergeben

105

Ich habe einen Lambda-Ausdruck, den ich gerne weitergeben und wiederverwenden möchte. Hier ist der Code:

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

Der Schlüssel hier ist, dass ich den Lambda-Ausdruck, den ich hier verwende, an die Methode übergeben kann, die diesen Code aufruft, damit ich ihn wiederverwenden kann. Der Lambda-Ausdruck ist das zweite Argument in meiner .Query-Methode. Ich gehe davon aus, dass ich eine Aktion oder eine Funktion verwenden möchte, bin mir aber nicht ganz sicher, wie die Syntax dafür lautet oder wie sie funktioniert. Kann mir bitte jemand ein Beispiel geben?

Adam Levitt
quelle
3
Machen Sie den Parameter zu einer Aktion oder einer Funktion.
Metro Schlumpf
Richtig, das dachte ich mir ... kannst du mir ein Beispiel zeigen, wie ich das machen würde?
Adam Levitt
Mögliches Duplikat von C # Lambda-Ausdrücken als Funktionsargumente
Benutzer

Antworten:

122

Verwenden Sie einen Func<T1, T2, TResult>Delegaten als Parametertyp und übergeben Sie ihn an 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>();   
  }  
}

Sie würden es nennen:

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

Oder weisen Sie das Lambda einer Variablen zu und übergeben Sie es .

Oded
quelle
Das sieht sehr gut aus und wie würde ich das Lambda AUSSEN dieser getJobs-Methode definieren? Mit anderen Worten, wie sieht die Zeile vor dem Aufruf von getJobs () aus, um das Lambda zu definieren?
Adam Levitt
@AdamLevitt - So wie Sie es mit Ihrem Beispielcode getan haben. Wird zur Antwort hinzufügen.
Oded
Können die Funktionsparameter auch trotzdem dynamisch sein?
Adam Levitt
@AdamLevitt - Sie können die Funktion generisch machen. Wenn Sie jedoch eine unterschiedliche Anzahl von Parametern für die Lambdas wünschen, benötigen Sie Überladungen.
Oded
Richtig. Eigentlich möchte ich verschiedene Implementierungen der IJob-Schnittstelle übergeben können, aber das funktioniert nicht mit Dappers Abfrage <>, da zur Laufzeit die eigentliche generische impl-Klasse erforderlich ist. Dies ist immer noch ziemlich nah an dem, was ich mir erhofft hatte.
Adam Levitt
27

Wenn ich verstehe, benötigen Sie folgenden Code. (Übergabe des Ausdrucks Lambda als Parameter) Die Methode

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
    }

Aufrufmethode

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

Sie können dasselbe in ihrer Klasse tun, siehe Beispiel.

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

Aufrufmethode

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

Ich hoffe das ist nützlich

Marinpietri
quelle
2
Können Sie erklären , warum wir das brauchen Compile()in der .Where? Ich habe gesehen, dass es auch ohne das funktioniert.
Sнаđошƒаӽ
7

Lambda-Ausdrücke haben den Typ Action<parameters>(falls sie keinen Wert zurückgeben) oder Func<parameters,return>(falls sie einen Rückgabewert haben). In Ihrem Fall haben Sie zwei Eingabeparameter und müssen einen Wert zurückgeben. Daher sollten Sie Folgendes verwenden:

Func<FullTimeJob, Student, FullTimeJob>
SztupY
quelle
5

Sie sollten einen Delegatentyp verwenden und diesen als Befehlsparameter angeben. Sie können einen der integrierten Delegattentypen verwenden - Actionund Func.

In Ihrem Fall sieht es so aus, als würde Ihr Delegat zwei Parameter verwenden und ein Ergebnis zurückgeben, sodass Sie Folgendes verwenden können Func:

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

Sie können dann Ihre GetJobsMethode aufrufen , die in einer Delegateninstanz übergeben wird. Dies kann eine Methode sein, die dieser Signatur entspricht, ein anonymer Delegat oder ein Lambda-Ausdruck.

PS Sie sollten PascalCase für Methodennamen verwenden - GetJobsnicht getJobs.

devdigital
quelle