Of course the idiomatic way to avoid problems at the boundary between your F# code and the outside world is to ensure that you only expose a small set of compatible types. This works pretty well if your clients are also .NET languages. For instance you can do things like exposing your collections as seq, rather than say, a native F# list, and this will mean your collections can be consumed as IEnumerable. The only problem is it means you’ve got the added burden of maintaining this mapping layer, because you’ll no doubt want to use the F# “native” types internally.
So, what options do we have if some of our F# types happen to leak into our public API? Luckily, lots. Let’s take a look at how some of the common F# constructs can be called from C#.
Unions
I talked about the power of discriminated unions a while back, so how do they map to C#? Interestingly the F# compiler generates a very simple OO type hierarchy, with an abstract base class that each of the cases derive from. This will mean that your calling code will need to use some casting, but don’t worry, you’re not back in the hell of runtime typing; there are a set of methods on the type that you can use to identify the case before you do the cast, so at least you get some compile time sanity checking.
Here’s a simple discriminated union that we’ll be using as an example:
type TestDU = | One of int * int | Two of string | Three |
If we wanted to use this type in F#, we’d do so like this:
// A function 'f' that takes an instance 't' of our union type let f t = match t with One (a,b) -> printf "Got One" | _ -> () // Apply our function with a particular TestDU union case let _ = f <| Two "foo" |
That’s pretty natural, as you’d expect. If we exposed the function f to C#, it looks like this:
void Module1.f(Module1.TestDU t) |
This means we have to create an instance of the TestDU type, but we’ll quickly discover it’s abstract. As I mentioned before, the F# compiler has generated a very simple class hierarchy, with the union cases being subtypes of TestDU, implemented as nested types (which are used quite extensively by the F# compiler). But if we try and instantiate one of these subtypes…?
Ouch: ‘No constructors defined’. Luckily, instead there are helper functions on the base class that will create instances for us, at least for those cases with arguments. The functions are prefixed with ‘New’, e.g.:
var one = Module1.TestDU.NewOne(1, 2); var two = Module1.TestDU.NewTwo("foo"); |
And slightly oddly, the parameterless cases (Three in our example) use a property on the base class instead:
var three = Module1.TestDU.Three; |
So now we can create instances of the union type to pass to the F# function.
But what if we’re returned one instead? It will be of type TestDU, so how do we know what case it actually is? And how do we get to the parameters? Well, as we know it’s going to be one of the subtypes, we could use the C# ‘is’ operator to determine its identity, but the base class also provides helper methods to do it for us, prefixed with Is, e.g.:
if (two.IsTwo) { var x = (two as Module1.TestDU.Two).Item; // Do something with x } |
As you can see, Item contains the case value. For tupled types this becomes Item1, Item2 etc.
Records
Records are immutable types that contain fields, they tend to be used quite a lot in F# code, and luckily using them from C# is very straightforward. The only thing to remember is that they’re only constructor is the one taking all of the field values (because they’re immutable), e.g.:
type TestRecord = { field1 : int field2 : string } |
Can be instantiated like this in C#:
var r = new Module1.TestRecord(1, "foo"); |
Functions
It’s usual in F# to use curried functions. That is, functions that can be applied one argument at a time, returning a partially applied function. It turns out that the compiler maps this type of function (when directly exposed, as a public function on a module, say) into its tupled equivalent, which makes them easily callable directly from C#. For instance:
let public adder a b = a + b |
Has a native F# signature of int -> int -> int, but results in a generated CIL function taking a tuple of two ints, with signature more like int * int -> int.
But there are more complicated cases; F# functions can take functions and return them. When we’re dealing with functions in a first-class way like this, we can use the generic Microsoft.FSharp.Core.FSharpFunc type. For example:
let public adder a b = a + b let public addOne = adder 1 |
Where addOne is a function that returns a partially applied function. Calling it from F# is a breeze:
let x = addOne 100 |
But from C# it’s a bit trickier. The function returns an FSharpFunc, that we then need to apply with Invoke:
Microsoft.FSharp.Core.FSharpFunc<int,int> f = Module1.addOne; var x = f.Invoke(100); |
Although obviously you can combine this into a single line, and remove some of the type signatures (which I tend to do as much as possible using var when writing C# code):
var x = Module1.addOne.Invoke(100); |
Things get even nastier if you happen to expose an F# function that takes a function. For example, a function that takes another function and applies it to two arguments:
let apply op a b = op a b |
In F# interactive we can see that this has the following, nicely generalised type signature:
val apply : ('a -> 'b -> 'c) -> 'a -> 'b -> 'c |
i.e. it’s a function that takes as its first argument a function that takes an ‘a and a ‘b and returns a ‘c, it also accepts the ‘a and ‘b to pass to this function, and returns the ‘c result. Clear as. We may well want to create a version of this that uses the integer operator +, which is trivial from F#:
let add a b = apply (+) a b |
So how does it look if we try and do that from C#? In a word: messy. We have to use the Microsoft.FSharp.Core.FuncConvert.ToFSharpFunc helper functions, along with the .NET framework Converter as a way of specifying a generic, value-returning function.
using Microsoft.FSharp.Core; ... var op = FuncConvert.ToFSharpFunc(new Converter<int, FSharpFunc<int, int>>((aa) => { return FuncConvert.ToFSharpFunc(new Converter<int, int>((bb) => { // The 'meat' of the function. Hmmm... return aa + bb; })); })); var zz = Module1.apply(op, 1, 2); |
Whoa. That’s enough for now. As you can see, the various different ways of interoperating between F# and C# range from the neat to the nasty. The trick is definitely to pick your battles. Think carefully about what you need to expose and remember it’s probably best not to cross the beams if you can avoid it.


