代码之家  ›  专栏  ›  技术社区  ›  Steve Ellinger

C中的委托与F中的函数作为一级值有什么区别?

  •  26
  • Steve Ellinger  · 技术社区  · 14 年前

    更具体地说,代表有哪些特性(如果有的话)作为F中的一级值不具有;作为一级值的函数有哪些特性(如果有的话)作为C中的代表不具有?

    2 回复  |  直到 14 年前
        1
  •  30
  •   Christian Klauser    14 年前

    委托和F“一级函数值”是完全不同的。

    this -指针与方法地址一起被捕获)。

    另一方面,函数值是抽象类的实现 FSharpFunc<,> (它以前被称为 FastFunc<,> 在正式发布F#)之前。调用通过普通的虚拟方法进行,这比委托调用快得多。

    因此,如果您可以通过抽象类/虚拟方法将函数“实现”为一级值,那么为什么微软要添加委托呢?

    • 在.NET 1.0/1.1中,没有泛型,因此必须为要使用的每个函数签名定义新的委托类型(=“函数类型”)。
    • (不,仅仅使用Java这样的接口是不算数的。:-P)

    Func<,> Action<> 为了一切?

    • 向后兼容性
    • 可以将委托链接在一起以形成新的委托。此机制用于在VB.NET版和C#。在幕后,事件实际上只是一个委托字段。使用 += 语法实际上是将事件处理程序委托添加到事件字段中的委托链中。

    除了事件之外,是否有理由使用委托

    是的,一:每一个 FSharpFunc<,> ,它包含lambda表达式*,是一个新类。在.NET中,类被编码在已编译程序集的元数据中。另一方面,委托不需要额外的元数据。代表 但是 例示 这些委托类型在元数据方面是免费的。

    但是,等等,C#lambda表达式/匿名方法不是也实现为隐藏类吗?

        2
  •  6
  •   thr    14 年前

    我只想补充一点,SealedSun的说法是不正确的:

    调用通过普通 虚拟方法,速度更快 而不是委托调用。那就是 首先是代表。

    F#函数并不比委托调用快,也许在.NET 1.0中就是这样,但现在,委托调用和调用虚拟方法的时间差不多了。

    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