Sonntag, 9. Mai 2010

Partial Function Application

Vor einiger Zeit habe ich angefangen mich mit F# zu beschäftigen weil ich die funktionalen Konzepte sehr interessant finde, besonders für meine tägliche Arbeit. Seit dem ist mir erst bewusst geworden das immer mehr funktionale Konzepte auch in C# Einzug erhalten. F# zu lernen hat mir geholfen zu erkennen welches Potential noch in C# steckt und wie man sich dieses erschließen kann.

In F# gibt es das Konzept der „Partial Function Application“. Es geht darum dass Parameter einer Methode oder Funktion gebunden oder vorbelegt werden, während andere Parameter ungebunden bleiben und somit von Methodenaufruf zu Methodenaufruf variieren können.

Hier ein Beispiel wie eine Umsetzung dieses Konzepts in C# aussehen könnte. Gegeben sei eine Hilfsklasse:

static class SomethingUtilities
{
/// <summary>
/// Do something.
/// </summary>
/// <param name="context">
/// Parameter welcher sich nicht ändert.
/// </param>
/// <param name="person">
/// Parameter welcher sich oft ändert.
/// </param>
public static void DoSomething(Context context, Person person)
{
if(context.IsConnectionOpen)
{

}
}
}

Der Methode DoSomething können zwei Parameter übergeben werden, ein Kontext – Objekt und ein Person – Objekt mit dem was angestellt werden soll. Das Kontext – Objekt ändert sich in diesem Beispiel nicht. Die Methode würde dann so wie erwartet aufgerufen werden:

SomethingUtilities.DoSomething(context, person1);
SomethingUtilities.DoSomething(context, person2);
SomethingUtilities.DoSomething(context, person3);

Wir sehen dass der Kontext sich nicht ändert jedoch aber das Person - Objekt. Es wäre schön den Kontext nur einmal zu setzen und anschließend mit den verschiedenen Person – Objekten weiter arbeiten zu können. Die Methoden würden dann wie folgt aufgerufen werden:

doSomething(person1);
doSomething(person2);
doSomething(person3);

Das Ziel lässt sich relativ einfach erreichen. Es muss zunächst eine Extension – Methode definiert werden welches auf dem Delegaten der Zielmethode aufgerufen werden kann. Weitere Parameter dieser Extension – Methode sind dann die Objekte welche sich erst einmal nicht mehr weiter verändern, in diesem Beispiel das Kontext – Objekt. Der Rückgabewert ist eine Funktion oder Methoden – Delegat, welches die freien Argumente entgegen nehmen kann. Hier eine mögliche Implementierung:

public static class Extensions
{
/// <summary>
/// Zeigt die Umsetzung von Partial
/// Method Application
/// </summary>
/// <param name="method">
/// Signatur der Methode dessen Parameter
/// gebunden werden soll.
/// Diese Methode ist das eigentliche
//// Ziel des Aufrufs.
/// </param>
/// <param name="context">
/// Parameter welcher gebunden
/// beziehungsweise vorbelegt wird.
/// </param>
/// <returns>
/// Delegate mit freien Parametern
/// </returns>
public static Action<Person> PinContextArgument
(this Action<Context, Person> method,
Context context)
{
return person => method(context, person);
}
}

Nun belegen wir die Ziel – Methode mit Argumenten vor:

var doSomething=((Action<Context, Person>)DoSomething).
PinContextArgument(context);

Geschafft :-). Die statische Methode ist mit einem Kontext bereits versehen und die Aufrufe können wie gewünscht getätigt werden ohne jedes Mal den Kontext zu übergeben.

doSomething(person1);
doSomething(person2);
doSomething(person3);

Die gezeigte Implementierung ist anwendungsspezifisch um das Beispiel möglichst einfach zu halten. Eine allgemeine Implementierung ist schnell realisiert.

Keine Kommentare:

Kommentar veröffentlichen