是否可以使用管道中缀运算符在返回的对象上调用方法?
示例,我有一个带有方法(Method1)的.Net类(Class1)。我现在可以这样编码:
let myclass = new Class1()
let val = myclass.Method1()
我知道我也可以这样编码
let val = new Class1().Method1()
但是我想能够管道它(我在下面使用?我不知道该怎么做):
new Class1()
|> ?.Method1()
此外,假设我有一个返回一个对象的方法,我想只引用它,如果该方法没有返回null(否则保释?)
new Class1()
|> ?.Method1()
|> ?? ?.Method2()
或者为了更清楚,这里有一些C#代码:
public void foo()
{
var myclass = new Class1();
Class2 class2 = myclass.Method1();
if (class2 == null)
{
return;
}
class2.Method2();
}
答案 0 :(得分:2)
您可以非常轻松地定义类似于(??)
运算符的内容(但运算符不能以问号开头):
let (~??) f x =
if (x <> null) then
f x
不幸的是,你的流水线代码需要更冗长一些(同样,请注意你可以删除new
关键字来调用构造函数):
Class1()
|> fun x -> x.Method1()
全部放在一起:
Class1()
|> fun x -> x.Method1()
|> ~?? (fun x -> x.Method2())
答案 1 :(得分:1)
使用自定义运算符作为'kvb'建议绝对是一种选择。在这种情况下,您可能会感兴趣的另一种方法是定义您自己的“计算表达式”,该表达式会在您指定的每个点自动执行null
值的检查。使用它的代码如下所示:
open System.Windows.Forms
// this function returns (0) null, or (1) btn whose parent is
// null or (2) button whose parent is not null
let test = function
| 1 -> new Button(Text = "Button")
| 2 -> new Button(Text = "Button", Parent = new Button(Text = "Parent"))
| _ -> null
let res =
safe { let! btn = test(2) // specify number here for testing
// if btn = null, this part of the computation will not execute
// and the computation expression immediately returns null
printfn "Text = %s" btn.Text
let! parent = btn.Parent // safe access to parent
printfn "Parent = %s" parent.Text // will never be null!
return parent }
如您所见,当您想要使用可能为“null”的值时,可以在计算表达式中使用let!
。可以定义计算表达式,以便在值为null
时立即返回null
,否则运行其余的计算。这是代码:
type SafeNullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) =
if v = null then null else f(v)
let safe = new SafeNullBuilder()
BTW:如果你想了解更多关于这一点,它与Haskell中的'Maybe'monad(或使用F#选项类型的计算)非常相似。