Suppose there is a F# definitions:
type Either<'a,'b> = | Left of 'a | Right of 'b
let f (i : int) : Either<int, string> =
    if i > 0
        then Left i
        else Right "nothing"
Function f is used in C# code:
var a = Library.f(5);
How the result value a could be pattern matched for data constructors? Something like: 
/*
(if a is Left x)
    do something with x
(if a is Right y)
    do something with y
*/
                Using F# discriminated unions from C# is a bit inelegant, because of how they are compiled.
I think the best approach is to define some members (on the F# side) that will simplify using the types from C#. There are multiple options, but the one I prefer is to define TryLeft and TryRight methods that behave similarly to Int32.TryParse (and so they should be familiar to C# developers using your F# API):
open System.Runtime.InteropServices
type Either<'a,'b> = 
  | Left of 'a 
  | Right of 'b
  member x.TryLeft([<Out>] a:byref<'a>) =
    match x with Left v -> a <- v; true | _ -> false
  member x.TryRight([<Out>] b:byref<'b>) =
    match x with Right v -> b <- v; true | _ -> false
Then you can use the type from C# as follows:
int a;
string s;
if (v.TryLeft(out a)) Console.WriteLine("Number: {0}", a);
else if (v.TryRight(out s)) Console.WriteLine("String: {0}", s);
You lose some of the F# safety by doing this, but that's expected in a language without pattern matching. But the good thing is that anybody familiar with .NET should be able to use the API implemented in F#.
Another alternative would be to define member Match that takes Func<'a> and Func<'b> delegates and invokes the right delegate with the value carried by left/right case. This is a bit nicer from the functional perspective, but it might be less obvious to C# callers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With