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

OMG*_*chy 19 .net f#

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

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

示例代码:

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

Eam*_*nne 32

printfn 它的各种表兄弟有几个优点:

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

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

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
Run Code Online (Sandbox Code Playgroud)

但是,在F#3.1之前,它也很慢.它足够快,足以让你跟上编码器,但如果你在某种形式的序列化中使用它,它可能会变成瓶颈.在F#3.1发布公告(该分布的Visual Studio 2013的一部分)声称显着提高性能,虽然我还没有证实这一点.

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


pad*_*pad 7

这里有一些printf类比的优点和缺点Console.WriteLine.

优点:

  • printfn 函数是类型安全的:

    printfn "This is an integer: %i" 5 // works
    printfn "This is an integer: %i" "5" // doesn't compile
    
    Run Code Online (Sandbox Code Playgroud)
  • 部分应用很容易,但由于过载次数过多printfn,情况并非如此Console.WriteLine:

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

缺点:

除了不能像@mydogisbox所提到的那样重用参数之外,类似printfn函数Console.WriteLine(由于使用反射)得多; 你不应该使用前者进行记录.