43 Stimmen

Richtiges Currying in C#

Gegeben eine Methode DoSomething die eine (parameterlose) Funktion annimmt und sie auf irgendeine Weise verarbeitet. Gibt es einen besseren Weg, um die "Überladungen" für Funktionen mit Parametern als das Schnipsel unten erstellen?

public static TResult DoSomething<TResult>(Func<TResult> func)
{
    //call func() and do something else
}

public static TResult DoSomething<T0, TResult>(
    Func<T0, TResult> func,
    T0 arg0)
{
    return DoSomething(() => func(arg0));
}

public static TResult DoSomething<T0, T1, TResult>(
    Func<T0, T1, TResult> func,
    T0 arg0, T1 arg1)
{
    return DoSomething(arg => func(arg, arg1), arg0);
}

public static TResult DoSomething<T0, T1, T2, TResult>(
    Func<T0, T1, T2, TResult> func,
    T0 arg0, T1 arg1, T2 arg2)
{
    return DoSomething(arg => func(arg, arg1, arg2), arg0);
}

1 Stimmen

1 Stimmen

Hier sind ein paar Beiträge, die interessant sein könnten, wenn Sie versuchen, Curry in C #: blogs.msdn.com/wesdyer/archive/2007/01/29/ diditwith.net/2007/10/23/…

0 Stimmen

+1 für den Wesdyer-Link - Sie erhalten ein wirklich solides Verständnis für einige weniger verständliche Konzepte, wenn Sie auch den zugehörigen Fibonacci-Beitrag lesen: blogs.msdn.com/b/wesdyer/archive/2007/02/02/

44voto

Jon Skeet Punkte 1325502

EDIT: Wie in den Kommentaren erwähnt, handelt es sich hier um eine Teilanwendung und nicht um ein Currying. Ich schrieb eine Blogbeitrag über mein Verständnis des Unterschieds die für viele interessant sein könnten.

Nun, es ist nicht sonderlich anders - aber ich würde den "Currying"-Teil von dem "DoSomething"-Teil trennen:

public static Func<TResult> Apply<TResult, TArg> (Func<TArg, TResult> func, TArg arg)
{
    return () => func(arg);
}

public static Func<TResult> Apply<TResult, TArg1, TArg2> (Func<TArg1, TArg2, TResult> func,
                                                          TArg1 arg1, TArg2 arg2)
{
    return () => func(arg1, arg2);
}

// etc

Dann:

DoSomething(Apply(foo, 1));

Auf diese Weise können Sie den Currying-Code in anderen Situationen wiederverwenden - auch in Fällen, in denen Sie den neu zurückgegebenen Delegaten nicht sofort aufrufen möchten. (Sie könnten ihn zum Beispiel später noch einmal aufrufen wollen).

4voto

leandromoh Punkte 119

Die Antwort von @Jon Skeet ist richtig, aber alle möglichen Überladungen von Hand zu schreiben ist etwas verrückt, also kann man eine Lib wie Curryfy die diese Aufgabe für Sie übernehmen. Die Bibliothek Curryfy stellt insbesondere die Erweiterungsmethoden Curry, UnCurry und ApplyPartial mit vielen Überladungen zur Verfügung.

2voto

Rodion Mostovoy Punkte 484

Hier ist die Methode, die es erlaubt, unbegrenzte Funktionsaufrufe zu schreiben, indem man dynamic (wie Curry in js):

dynamic Sum(int a)
{
    Console.WriteLine(a);
    return new Func<int, dynamic>(b => Sum(a + b));
}

Wenn Sie es so nennen Sum(2)(3)(4)(10) wird die Ausgabe sein:

2
5
9
19

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X