[英]What is the difference between delegates in C# and functions as first class values in F#?
更具体地说,代表具有作为F#中的第一类值的函数的特征(如果有的话)没有; 作为第一类值的特征有什么特征(如果有的话)在C#中委托没有?
代表和F#“一流的功能价值”是完全不同的。
委托是CLR的一种机制,它是一个围绕函数指针+对象对的类型安全包装器(例如方法, this
-pointer与方法地址一起被捕获)。
另一方面,F#函数值是抽象类FSharpFunc<,>
(它曾经在F#正式发布之前被称为FastFunc<,>
)。 调用通过普通的虚方法发生,这比委托调用快得多。 这就是F#-team首先不使用委托的原因。
因此,如果您可以通过抽象类/虚方法“实现”作为第一类值的函数,为什么Microsoft会添加委托?
好的,但是从.NET 2.0开始我们有Generics,为什么我们还有代表呢? 为什么我们不能只使用Func<,>
和Action<>
来做所有事情?
+=
语法,您实际上将事件处理程序委托添加到事件字段中的委托链。 除了事件,是否有理由使用委托而不是FSharpFunc<,>
是的,一: FSharpFunc<,>
每个实现,包括lambda-expressions *,都是一个新类。 在.NET中,类编译在已编译程序集的元数据中。 另一方面,代表不需要额外的元数据。 委托类型可以,但实例化这些委托类型在元数据方面是免费的。
但是等等,C#lambda-expressions /匿名方法是不是实现为隐藏类?
是的,C#lambdas占据了两个世界中最糟糕的^^
我只是想补充说SealedSun的这句话不是真的:
调用通过普通的虚方法发生,这比委托调用快得多。 这就是F#-team首先不使用委托的原因。
F#函数并不比委托调用快,可能是.NET 1.0中的情况,但现在委托调用和调用虚拟方法几乎相当。
与调用委托相比,调用编译器静态绑定的F#函数也非常慢。
open System
open System.Diagnostics
let time name f =
let sw = new Stopwatch()
sw.Start()
f()
sw.Stop()
printfn "%s: %dms" name sw.ElapsedMilliseconds
time "delegate call" (
fun () ->
let f =
new Func<int, int, int>(
fun i1 i2 ->
let y = i1 + i2
let x = y + i1
let z = x + y + i2
z + x + y + i1
)
let mutable r = 0
for i = 0 to 10000000 do
r <- f.Invoke(i, i)
)
let f i1 i2 =
let y = i1 + i2
let x = y + i1
let z = x + y + i2
z + x + y + i1
time "fsharp func (static bound)" (
fun () ->
let mutable r = 0
for i = 0 to 10000000 do
r <- f i i
)
let make f =
let mutable r = 0
for i = 0 to 10000000 do
r <- f i i
time "fsharp func (dynamic bound)" (
fun () -> make f
)
Console.ReadLine() |> ignore
在我的计算机上生成以下结果
delegate call: 65ms
fsharp func (staticly linked): 4ms
fsharp func (dynamic invoke): 356ms
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.