F#中的System.Console.WriteLine()vs printfn

时间:2013-06-12 17:43:28

标签: .net f#

F#中的以下两个语句有什么区别? 它们相比是否有任何优点或缺点(不包括明显的语法差异)?

我知道WriteLine()是.NET的一部分,但不明白它可能带来什么影响。

示例代码:

printfn "This is an integer: %d" 5
System.Console.WriteLine("This is an integer: {0}" , 5)

4 个答案:

答案 0 :(得分:31)

printfn及其各种堂兄弟有几个好处:

  • 他们更短
  • 他们可以做一些静态类型检查;即printfn "%d" "bad type"将无法编译。
  • ...但您不必进行静态类型检查; %O打印任何对象
  • 他们可以使用%A打印“智能”表示,例如数组,元组和有区别的联合
  • 它们可以部分应用;即printfn "%d, %d" 3是有效的表达式。这是特别好的,因为编译器可以在您稍后使用此子表达式时检查您是否实际应用了正确数量的参数 - 与Console.WriteLine不同,它会很乐意接受太多或太少的参数。

实际上,最常见的部分应用程序可能只包含格式字符串; e.g。

let printParticle = printfn "Particle at (%d, %d), state %A, p = %f"

printParticle 2 3 //compile time warning about ignored value
printParticle 3 4 someState 0.4 //fine
printParticle 5 6 someState 0.4 0.7 //compile-time error

然而,在F#3.1之前,它还。它足够快,足以让你跟上编码器,但如果你在某种形式的序列化中使用它,它可能会变成瓶颈。 F# 3.1 release announcement(作为Visual Studio 2013的一部分发布)声称可以显着提高性能,但我还没有对此进行验证。

就个人而言,我通常使用printfn进行探索性编码,然后我很大程度上坚持%A并偶尔引入其他说明符。但是,.NET本机字符串格式在某些情况下对于其详细的文化仍然有用和格式相关的选项。如果你想要最大速度直接连接(或StringBuilder)将轻松胜过两者,因为这样可以避免解释格式字符串。

答案 1 :(得分:7)

以下是与printf相比较的Console.WriteLine类功能的优缺点。

优点:

  • printfn函数是类型安全的:

    printfn "This is an integer: %i" 5 // works
    printfn "This is an integer: %i" "5" // doesn't compile
    
  • 使用printfn进行部分应用很容易,但由于过载次数过多,Console.WriteLine不是这种情况:

    [1; 2; 3] |> List.iter (printfn "%i; ")
    
  • printfn通过%A说明符更好地支持F#类型。

缺点:

除了不能像@mydogisbox那样重用参数,printfn-like functions are much slower而不是Console.WriteLine(由于使用反射);你不应该使用前者进行记录。

答案 2 :(得分:4)

除了样式之外,System.Console.WriteLine还具有能够重用参数的优势,即System.Console.WriteLine("This is a integer twice: {0} {0}", 5)

另外,正如所提到的here,您可以使用printfn来完成F#对象的漂亮打印,而System.Console.WriteLine无法对其进行打印,因为它不需要元组,所以可以用它做部分应用。

正如其他人所说,printfn使用反射,因此明显慢于PrintLine,但也是类型安全的。

答案 3 :(得分:4)

可以部分应用printfn功能。

let printDouble = printfn "%f"
printDouble 2.0

由于标准.NET函数将元组作为F#中的参数,因此不能在那里使用部分应用程序。

printfn的第二个优点是,参数是键入的。所以这不会编译:

let printDouble = printfn "%d"
printDouble 2.0