F# and C# being bros

All chill and working together and stuff

By Adam Guest - 21 January 2016

Sometimes, you're just coding away in C# trying to be productive and stuff, and then you realise that this would all be easier in F#. But you can't just switch your whole project over to F# (probably because some Project Manager would get mad or something) - but maybe with a bit of interop magic you can get these two .NET languages to be bros and work together nicely. That way, you get to write glorious F# code, but use a bunch of the C# stuff that's already been done.

F# can use all those objects

Like, yeah, in case you were wondering f# can interact with the rest of the .NET world through objects and stuff. Also, since F# 4.0 object constructors are now grown up functions like everything else which means you can use them in pipe chains (I was really excited when I learned this part).

open System

let makeUri s = "http://" + s |> Uri

F# can make pretty C# classes

This one is obvious given that it can talk to the rest of the .NET world pretty easily, but yes F# can make classes that C# can understand. Interfaces too! This is how you can make some snazzy F# functions and call them from C# code.

type ISomeInterface =
    abstract DoAnInterfaceyThing : string -> string
    
type SomeClassThatImplementsAnInterface () =
    interface ISomeInterface with
        member x.DoAnInterfaceyThing msg =
            "Interface!" + msg
    member x.DoAClassThing a = a + 1

These are full fledged classes and interfaces, so you could also implement an interface defined in F# with a class in C# or vice versa. The big difference is when making static classes - there isn't a proper attribute for that (turns out C# has just been lying to you all this time to make things easier) - but you can still make a static class(ish), just make a sealed class with a private constructor and no instance members:

[<Sealed>]
type StaticishClass private () =
    static member DoThing a = a + 1

C# can give F# functions

This is possibly the least elegant part of the whole shebang, but if you have some C# code that you would like to pass to an object created in F# as a Func (which is totally a thing you want to do) you will soon come to notice that a C# Func and an F# function are different things. Fortunately, with some fancy F# plumbing that I found over here you can convert your C# trash into glorious F# functions with a tiny little extension method.

open System.Runtime.CompilerServices

[<Extension>]
type public FSharpFuncUtil = 
    
    [<Extension>] 
    static member ToFSharpFunc<'a> (func:System.Func<'a>) = fun () -> func.Invoke()

    [<Extension>] 
    static member ToFSharpFunc<'a,'b> (func:System.Converter<'a,'b>) = fun x -> func.Invoke(x)

    [<Extension>] 
    static member ToFSharpFunc<'a> (func:System.Action<'a>) = fun x -> func.Invoke(x)

    [<Extension>] 
    static member ToFSharpFunc<'a,'b> (func:System.Action<'a,'b>) = fun x -> func.Invoke(x)

    [<Extension>] 
    static member ToFSharpFunc<'a,'b> (func:System.Func<'a,'b>) = fun x -> func.Invoke(x)

    [<Extension>] 
    static member ToFSharpFunc<'a,'b,'c> (func:System.Func<'a,'b,'c>) = fun x y -> func.Invoke(x,y)

    [<Extension>] 
    static member ToFSharpFunc<'a,'b,'c,'d> (func:System.Func<'a,'b,'c,'d>) = fun x y z -> func.Invoke(x,y,z)

    static member Create<'a> (func:System.Func<unit, 'a>) = FSharpFuncUtil.ToFSharpFunc func

    static member Create<'a,'b> (func:System.Func<'a,'b>) = FSharpFuncUtil.ToFSharpFunc func

    static member Create<'a,'b,'c> (func:System.Func<'a,'b,'c>) = FSharpFuncUtil.ToFSharpFunc func

    static member Create<'a,'b,'c,'d> (func:System.Func<'a,'b,'c,'d>) = FSharpFuncUtil.ToFSharpFunc func

This then means that you can define a class in F# that would take an F# function:

type SomeClassWithADependency (funcThing : string -> string) =
    member x.DoThing(s) = funcThing s

Then you can inject it from your C# code:

public static class FunctionContainer
{
  public static string SomeStringFunction(string input) => "So, gosh-darned creative:" + input;
}

public static class Injector
{
  public static SomeClassWithADependency GetTheThing() =>
    new SomeClassWithADependency(FunctionContainer.SomeStringFunction.ToFSharpFunc());
}

Async is also awesome

If you've added async methods to your code, you might've noticed how it spreads itself around like a virus and now everything returns a Task. F# has a different way of working with async compared to C#, but handily it also provides a neat set of functions for moving between Async<'a> and Task<T>.

let anAsyncFunction thing =
  async {
    //a task becomes an async
    return! Task.FromResult(thing) |> Async.AwaitTask
  }
  
//and back again!
let nowItsATask =
  "yo" |> anAsyncFunction |> Async.StartAsTask 

And so they both lived happily ever after...