背景
我最近读到 .NET 4 的 System.String 类具有 Join 方法的新重载。这个新的重载需要一个分隔符和一个IEnumerable<T>
允许将任意集合连接成单个字符串的方法,而无需转换为中间字符串数组。
凉爽的!这意味着我现在可以这样做:
var evenNums = Enumerable.Range(1, 100)
.Where(i => i%2 == 0);
var list = string.Join(",",evenNums);
...而不是这个:
var evenNums = Enumerable.Range(1, 100)
.Where(i => i%2 == 0)
.Select(i => i.ToString())
.ToArray();
var list = string.Join(",", evenNums);
...从而节省将每个项目转换为字符串,然后分配数组。
问题
但是,作为一般编程风格的粉丝,特别是 C# 中的方法链接,我希望能够编写如下内容:
var list = Enumerable.Range(1, 100)
.Where(i => i%2 == 0)
.string.Join(",");
虽然这不是合法的 C#。是的,我可以用 来做Enumerable.Aggregate
,是的,我可以用我自己的 Join 扩展方法来做),但是这些方法很难阅读/效率低下,并且感觉像是一种逃避(分别)所以我想尝试做这是一种不同的方式。到目前为止,我设法得到的最接近的是:
var list = Enumerable.Range(1, 100)
.Where(i => i%2 == 0)
.ApplyTo(
Functional.Curry<string, IEnumerable<object>, string>
(string.Join)(",")
);
...使用以下扩展方法:
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);
}
}
这非常冗长,需要显式定义参数和字符串的返回类型。我要使用的加入重载,并且依赖于 C#4 的方差特性,因为我们将参数之一定义为 IEnumerable 而不是 IEnumerable。
挑战
你能找到一种使用方法链式编程的更简洁的方法吗?
这个挑战是关于尝试在 C# 中找到一种简洁的方式来对具有多个重载的函数进行 curry - 这只是为了好玩!