在最新版本的C#中,我可以执行this之类的操作吗?
我觉得linq是最接近的,但那是链接,而不是功能组合,对吗?
答案 0 :(得分:15)
public static class Extensions
{
public static Func<T, TReturn2> Compose<T, TReturn1, TReturn2>(this Func<TReturn1, TReturn2> func1, Func<T, TReturn1> func2)
{
return x => func1(func2(x));
}
}
用法:
Func<int, int> makeDouble = x => x * 2;
Func<int, int> makeTriple = x => x * 3;
Func<int, string> toString = x => x.ToString();
Func<int, string> makeTimesSixString = toString.Compose(makeDouble).Compose(makeTriple);
//Prints "true"
Console.WriteLine(makeTimesSixString (3) == toString(makeDouble(makeTriple(3))));
答案 1 :(得分:13)
我没有让编译器检查这个,但这应该是可能的:
Func<T3,T1> my_chain(Func<T2,T1> f1, Func<T3,T2> f2)
{
return (x=> f2(f1(x)));
}
答案 2 :(得分:10)
在C#中没有特定的运算符/“语法糖”(但是,在F#中,您将使用>>
运算符)。
Matthew Podwysocki对此主题有一个 great blog post 。他在C#中建议了这种结构:
public static class FuncExtensions
{
public static Func<TSource, TResult> ForwardCompose<TSource, TIntermediate, TResult>(
this Func<TSource, TIntermediate> func1, Func<TIntermediate, TResult> func2)
{
return source => func2(func1(source));
}
}
Func<Func<int, int>, IEnumerable<int>, IEnumerable<int>> map = (f, i) => i.Select(f);
Func<Func<int, bool>, IEnumerable<int>, IEnumerable<int>> filter = (f, i) => i.Where(f);
Func<int, Func<int, int, int>, IEnumerable<int>, int> fold = (s, f, i) => i.Aggregate(s, f);
// Compose together
var mapFilterFold = map.Apply(x => x * x * x)
.ForwardCompose(filter.Apply(x => x % 3 == 0))
.ForwardCompose(fold.Apply(1, (acc, x) => acc * x));
Console.WriteLine(mapFilterFold(Enumerable.Range(1, 10)));
答案 3 :(得分:6)
C#没有一流的支持,但实施起来并不是特别困难。你只需要编写很多重载。
public static class Composition
{
public static Func<T2> Compose<T1, T2>(Func<T1> f1, Func<T1, T2> f2)
{
return () => f2(f1());
}
public static Func<T1, T3> Compose<T1, T2, T3>(Func<T1, T2> f1, Func<T2, T3> f2)
{
return v => f2(f1(v));
}
}
答案 4 :(得分:4)
它不是那么漂亮,但你可以做到:
Func<IEnumerable<T>, IEnumerable<T>> desort = l => l.OrderBy(i => i).Reverse();
或者,如果你想要更复杂的东西(它在阵列上起作用):
Action<int[]> desort = a => Array.Reverse(Array.Sort(a));
假设存在这些方法......但语法应该是正确的。
然后您可以通过以下方式使用它(假设您使用了上面的第一种方法):
var arr = { 2,8,7,10,1,9,5,3,4,6 };
var desortedArr = desort(arr);
答案 5 :(得分:3)
不仅仅是Linq,它是委托,还有与链接类似的lambda表达式/语句。
Func<int, string> a = p => p.ToString();
Func<string, string> b = p => "|" + p + "|";
Func<int, string> c = p => b(a(p));
链接中给出的定义是:
函数组合是将一个函数的结果流水线化为另一个函数的输入,创建一个全新的函数。
而且c
显然是一个链接调用a
和b
的新功能。
答案 6 :(得分:1)
不,不缺少定义自己的通用Compose<T, U...>()
函数。 C#没有内置功能来帮助您解决这个问题。 (它也没有部分应用。)
答案 7 :(得分:0)
C#中的函数组合示例
f(x)°g(x)
Func<int, int> f = x => x + 2;
Func<int, int> g = x => 3 * x;
Func<int, int> b = x => f(g(x));
int result = b(2); //Result is 8