Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between delegates in C# and functions as first class values in F#?

More specifically what are the characteristics (if any) that delegates have that functions as first class values in F# don't have; and what are the characteristics that functions as first class values have (if any) that delegates in C# don't have?

like image 818
Steve Ellinger Avatar asked Oct 09 '10 19:10

Steve Ellinger


People also ask

What is difference between delegate and method?

Delegates allow methods to be passed as parameters. Delegates can be used to define callback methods. Delegates can be chained together; for example, multiple methods can be called on a single event. Methods don't have to match the delegate type exactly.

What are delegates C?

A delegate is a type that safely encapsulates a method, similar to a function pointer in C and C++. Unlike C function pointers, delegates are object-oriented, type safe, and secure. The type of a delegate is defined by the name of the delegate.

What is the difference between delegate and interface?

Delegates and Interfaces are two distinct concepts in C#. Interfaces allow to extend some object's functionality, it's a contract between the interface and the object that implements it, while delegates are just safe callbacks, they are a sort of function pointers.

What is the relationship between events and delegates in C#?

Event is a notification raised by an object to signal the occurrence of an action. Delegate is associated with the event to hold a reference of a method to be called when the event is raised.


2 Answers

Delegates and F# "First class function values" are quite different.

Delegates are a mechanism of the CLR, a type-safe wrapper around function-pointer+object pairs (for instance methods, the this-pointer gets captured together with the method address).

F# function values on the other hand, are implementation of an abstract class FSharpFunc<,> (it used to be called FastFunc<,> before the official release of F#). Invocation happens via ordinary virtual methods, which is much faster than delegate invocation. That is the reason the F#-team didn't use delegates in the first place.

So if you can "implement" functions as first class values via abstract classes/virtual methods, why did Microsoft add delegates?

  • There was no alternative In .NET 1.0/1.1, there were no generics, so you had to define a new delegate type (="function type") for every function signature you wanted to use.
  • (No, just using interfaces like in Java doesn't count. :-P )

Ok, but we have Generics since .NET 2.0, why do we still have delegates? Why can't we just use Func<,> and Action<> for everything?

  • Backwards compatibility
  • Multicast Delegates Delegates can be chained together to form new delegates. This mechanism is used to implement events in VB.NET and C#. Behind the scenes, an event is really just a single delegate field. Using the += syntax you essentially add your event-handler-delegate to the chain of delegates in the event field.

Apart from events, is there a reason to use delegates over FSharpFunc<,>

Yes, one: Each and every implementation of FSharpFunc<,>, that includes lambda-expressions*, is a new class. And in .NET classes are encoded in the metadata of the compiled assembly. Delegates on the other hand require no extra metadata. The delegate types do but instantiating these delegate types is free in terms of metadata.

But wait, aren't C# lambda-expressions/anonymous methods too implemented as hidden classes?

Yes, C# lambdas take the worst of both worlds ^^

like image 139
Christian Klauser Avatar answered Sep 25 '22 02:09

Christian Klauser


I just wanted to add that this statement from SealedSun isn't true:

Invocation happens via ordinary virtual methods, which is much faster than delegate invocation. That is the reason the F#-team didn't use delegates in the first place.

F# functions are not faster then delegate invocation, maybe that was the case back in .NET 1.0, but now a days delegate invocation and invoking virtual methods are pretty much on-par.

Also invoking F# functions that can't be bound statically by the compiler is very slow compared to invoking a delegate.

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 

Produces the following results on my computer

delegate call: 65ms fsharp func (staticly linked): 4ms fsharp func (dynamic invoke): 356ms 
like image 41
thr Avatar answered Sep 23 '22 02:09

thr