Hintergrund
Ich habe kürzlich gelesen, dass die Klasse System.String von .NET 4 eine neue Überladung der Join-Methode hat. Diese neue Überladung nimmt ein Trennzeichen und eine IEnumerable<T>
die es ermöglicht, beliebige Sammlungen zu einer einzigen Zeichenkette zusammenzufassen, ohne dass eine Konvertierung in ein dazwischenliegendes String-Array erforderlich ist.
Klasse! Das bedeutet, dass ich das jetzt tun kann:
var evenNums = Enumerable.Range(1, 100)
.Where(i => i%2 == 0);
var list = string.Join(",",evenNums);
...stattdessen:
var evenNums = Enumerable.Range(1, 100)
.Where(i => i%2 == 0)
.Select(i => i.ToString())
.ToArray();
var list = string.Join(",", evenNums);
...und spart damit die Konvertierung jedes Elements in eine Zeichenkette und die anschließende Zuweisung eines Arrays.
Das Problem
Da ich jedoch ein Fan des funktionalen Stils der Programmierung im Allgemeinen und der Methodenverkettung in C# im Besonderen bin, würde ich es vorziehen, so etwas schreiben zu können:
var list = Enumerable.Range(1, 100)
.Where(i => i%2 == 0)
.string.Join(",");
Dies ist jedoch kein legales C#. Ja, ich könnte tun Sie es mit Enumerable.Aggregate
und ja, ich könnte es mit meiner eigenen Join-Extension-Methode machen ), aber diese Ansätze sind schwer lesbar/ineffizient und fühlen sich wie ein Ausweg an (bzw.), also würde ich gerne versuchen, es anders zu machen. Das, was ich bisher am ehesten geschafft habe, ist dies:
var list = Enumerable.Range(1, 100)
.Where(i => i%2 == 0)
.ApplyTo(
Functional.Curry<string, IEnumerable<object>, string>
(string.Join)(",")
);
...unter Verwendung der folgenden Erweiterungsmethoden:
public static class Functional
{
public static TRslt
ApplyTo<TArg, TRslt>(this TArg arg, Func<TArg, TRslt> func)
{
return func(arg);
}
public static Func<T1, Func<T2, TResult>>
Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
{
Func<Func<T1, T2, TResult>, Func<T1, Func<T2, TResult>>> curried
= f => x => y => f(x, y);
return curried(func);
}
}
Dies ist ziemlich langatmig, erfordert eine explizite Definition der Parameter und des Rückgabetyps der string.Join-Überladung, die ich verwenden möchte, und stützt sich auf die Varianzfunktionen von C#4, da wir eines der Argumente als IEnumerable und nicht als IEnumerable definieren.
Die Herausforderung
Können Sie einen besseren Weg finden, dies zu erreichen? Anwendung des methodenverkettenden Programmierstils ?
In dieser Herausforderung geht es darum, in C# einen kurzen Weg zu finden, um eine Funktion mit mehreren Überladungen zu curryen - und das nur zum Spaß!