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

C#中的委托与F#中作为一级值的函数之间有什么区别?,c#,f#,delegates,first-class-functions,C#,F#,Delegates,First Class Functions,更具体地说,代表具有哪些作为F#中的一级值所没有的特征(如果有的话);作为一级值的函数有哪些C#中的委托所没有的特性(如果有的话?委托和F#“一级函数值”是完全不同的 委托是CLR的一种机制,是围绕函数指针+对象对的类型安全包装(例如方法,this-指针与方法地址一起捕获) 另一方面,F#函数值是一个抽象类的实现FSharpFunc(在F#正式发布之前,它曾被称为FastFunc)。调用通过普通的虚拟方法进行,这比委托调用快得多。 这就是F#团队最初没有使用代理的原因 那么,如果您可以通过抽象类

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

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

委托是CLR的一种机制,是围绕函数指针+对象对的类型安全包装(例如方法,
this
-指针与方法地址一起捕获)

另一方面,F#函数值是一个抽象类的实现
FSharpFunc
(在F#正式发布之前,它曾被称为
FastFunc
)。调用通过普通的虚拟方法进行,这比委托调用快得多。 这就是F#团队最初没有使用代理的原因

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

  • 在.NET 1.0/1.1中没有替代方法,没有泛型,因此必须为要使用的每个函数签名定义一个新的委托类型(=“函数类型”)
  • (不,仅仅使用Java中的接口并不重要。:-P)
好的,但是从.NET2.0开始我们就有泛型了,为什么我们还有委托呢?为什么我们不能对所有事情都使用
Func
Action

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

是的,一个:
FSharpFunc
的每个实现,包括lambda表达式*,都是一个新类。NET中的类在已编译程序集的元数据中进行编码。另一方面,委托不需要额外的元数据。委托类型没有,但实例化这些委托类型在元数据方面是免费的

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


是的,C#lambdas两全其美^ ^

我只想补充一点,SealedSun的这句话是不正确的:

调用通过普通的 虚拟方法,这要快得多 而不是委托调用。这就是问题所在 F队没有使用的原因 首先是代表

F#函数的速度并不比委托调用快,也许在.NET1.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

@delnan,你不知道为什么你认为代表们被拴在C#上;Anders等人从一开始就将其纳入语言设计中。事实上,他在C#之前就已经在J++中包含了它们。至于代理是一个丑陋的实现,这是主观的,因此没有信息。如需参考,请参阅“C#lambdas双管齐下”:用一种多么悲观的方式来表达。。。但我明白你的意思;)我是否可以从你的回答中推断出,在F#中作为一级值发挥作用?与代理相比,唯一的优势是速度?函数中是否没有任何一类值会在我编写程序的方式中引入范式转换?在C#3.0中,这一点非常接近。在2.0中,委托编写起来非常麻烦(语法非常繁重),以至于您很少使用它们。F#型推理也有帮助。也就是说,我想说的是“语法糖的优势”导致了范式转换。请参阅,作为这方面的证据。@SealedSun:在以通用方式支持适当的高级函数操作(组合等)之前,不能真正调用C#FP语言。虽然我很喜欢模式匹配和简单的不变性,但严格来说,它们并不是FP的关键。@pblasucci函数组合、const和flip只是库函数。它们是.NET4.0的一部分,以FSharp运行时库的形式出现。但真正缺少的是自动咖喱和partial.application的良好语法。我相信你是对的,有一次我链接到了一个采访.Net团队的人,在那里讨论了这一点(虚拟vs委托)。然而,这并不完全是我的问题所在,编程语言似乎在激增,而F#和“功能”编程是当今的热门词汇。我想问的是,选择函数作为第一类价值观是否是一种哲学上的转变,值得研究,或者主要是以更客观的方式进行宣传(或营销)(这样我的问题就不会结束了)。
delegate call: 65ms
fsharp func (staticly linked): 4ms
fsharp func (dynamic invoke): 356ms