【发布时间】:2008-12-03 10:41:07
【问题描述】:
继续my investigation 在 C# 中表达 F# 的想法,我想要一个管道转发运算符。对于包含在 IEnumerable 中的任何内容,我们已经拥有它,您可以随意使用 .NextFunc()。但是,例如,如果您在最后有任何类似折叠的缩减,则不能将其结果输入到函数中。
这里有两种扩展方法,我想知道是否有其他人尝试过,以及这是否是个好主意(编辑:现在包括Earwicker's Maybe):
public static void Pipe<T>(this T val, Action<T> action) where T : class
{ if (val!=null) action(val); }
public static R Pipe<T, R>(this T val, Func<T, R> func) where T : class where R : class
{ return val!=null?func(val):null; }
你可以这样写:
Func<string, string[]> readlines = (f) => File.ReadAllLines(f);
Action<string, string> writefile = (f, s) => File.WriteAllText(f, s);
Action<string, string> RemoveLinesContaining = (file, text) =>
{
file.Pipe(readlines)
.Filter(s => !s.Contains(text))
.Fold((val, sb) => sb.AppendLine(val), new StringBuilder())
.Pipe((o) => o.ToString())
.Pipe((s) => writefile(file, s));
};
(我知道,Filter == C# 中的 Where,Fold==Aggregate,但我想自己动手,我本可以做 WriteAllLines,但这不是重点)
编辑:根据 Earwicker 的评论进行更正(如果我理解正确的话)。
【问题讨论】:
-
我认为这叫作曲,而不是管道。
-
不,但它们是相关的,请看这里:blogs.msdn.com/chrsmith/archive/2008/06/14/…
-
几个错误:你需要一个约束'where T : class',否则你不能与 null 比较。此外,您只在 Func 版本中检查了 null 。在理想的世界中,您只需要编写 Func 版本 - 请参阅 stackoverflow.com/questions/27731/whats-wrong-with-c#303071中的“void”@
-
您可能会惊讶地发现(我曾经)可以在空变量上调用扩展方法。试试这个:
public static bool IsNull(this object obj) { return (obj == null); } -
@Mark,据我所知,没有办法直接使用构造函数来实现。您必须创建一个静态“构造函数”(如
Tuple.Create),即使这样也不能使用多个参数(我认为:我还没有尝试过)
标签: c# f# functional-programming