6

I am trying to use FSharpChoice type in a C# project. I have created a choice like so

var a = FSharpChoice<T1,T2,T3>.NewChoice1Of3(instofT1);

now how do I get instofT1 out of the choice type.

I see I can do a IsChoice1Of3 but how do i get to the value in the choice object?

Pradeep
  • 4,099
  • 4
  • 31
  • 45
  • Also see [discriminated-union-in-c-sharp](http://stackoverflow.com/questions/3151702/discriminated-union-in-c-sharp) – nawfal Jul 15 '14 at 11:05

3 Answers3

6

I probably wouldn't use the type directly from C# - you can do that, but the resulting code won't be very nice. I'd probably declare my own Choice type that would look like this:

type Choice<'T1, 'T2> private (opt1, opt2) =
  member x.TryGetChoice1Of2(arg:byref<'T1>) = //'
    match opt1 with
    | Some v -> arg <- v; true
    | _ -> false
  // Similar code for 'TryGetChoice2Of2'

type Choice = // static methods for creating (Choice1Of2, ...)

This uses byref parameters which appear as out parameters in C#, so you could write:

int num;
string str;
if (choice.TryGetChoice1Of2(out num)) // ...
else if (choice.TryGetChoice2Of2(out str)) // ...
else // assert(false)

This is definitely more pleasant way of working with the type from C# (and it uses pattern familiar from, for example, working with Int32.TryParse).

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • 3
    I like this approach, but I like Juliet's approach in this other answer even better: http://stackoverflow.com/questions/3151702/discriminated-union-in-c/3199453#3199453. – kvb Feb 23 '11 at 23:54
  • Which I'd translate as `type IChoice<'a,'b,'c> = abstract Match : Func<'a, 't> * Func<'b, 't> * Func<'c, 't> -> 't` in F#. – kvb Feb 23 '11 at 23:59
  • @kvb: Yes, that looks very nice too. (I'd say nicer & more functional, but a bit less csharpish :-)) – Tomas Petricek Feb 24 '11 at 00:10
5

Cast the value to FSharpChoice<T1,T2,T3>.Choice1Of3 and use the Item property.

See Compiled Form of Union Types for Use from Other CLI Languages (archived, latest) in the F# spec for more information about how discriminated unions are represented.

Zoey Hewll
  • 4,788
  • 2
  • 20
  • 33
kvb
  • 54,864
  • 2
  • 91
  • 133
3

I recently started a project to make a "compatibility layer" so that FSharp.Core can be more easily consumed from C#. In particular, it makes generic discriminated unions usable from C#, for example:

var choice = Choice.New1Of3<int,string,string>(100);
int r = choice.Match(i => i + 21, s => s.Length + 1, s => s.Length + 5);

This does pattern matching on the discriminated union, similarly to how you would do it in F#, except there are no names.

Mauricio Scheffer
  • 98,863
  • 23
  • 192
  • 275