F# Immutable Class Interop
How do F# immutable types interface with C#. I'm just starting to learn F# and I'd like to mix it in with some C# code I have, but I want my F# classes to be immutable.
Let's say we're making a Vector class in F#. Vector.X开发者_如何学C and Vector.Y should be re-assignable, but only be returning a new Vector class. In C# this would take allot of legwork to make .WithX(float x) clone the existing object and return a new one. Is there an easy way to do this in F#?
I've been searching for some time and I can't seem to find any docs on this. So any help would be great.
And finally, if I imported this class into C# what would its interface look like? Will the F# code restrict me from doing something stupid like Vector.X = 10
?
This will look similar regardless of whether it's C# or F#.
You say "in C# it will take legwork", but cmon, I think
Vector WithX(float x) { return new Vector(x, this.Y); }
is it, right?
In both C# and F#, to prevent assignment to the X property, you author a property with a 'getter' but no 'setter'.
I think you're making all of this out to be harder than it is, or maybe I'm misunderstanding what you're asking.
EDIT
For the (I think rare) case of where there are 20 field and you may want to change just a small arbitrary subset of them, I found a cute hack to use F# and C# optional parameters together nicely.
F# Code:
namespace global
open System.Runtime.InteropServices
type Util =
static member Some<'T>(x:'T) = Some x
type MyClass(x:int, y:int, z:string) =
new (toClone:MyClass,
[<Optional>] ?x,
[<Optional>] ?y,
[<Optional>] ?z) =
MyClass(defaultArg x toClone.X,
defaultArg y toClone.Y,
defaultArg z toClone.Z)
member this.X = x
member this.Y = y
member this.Z = z
F# client code:
let a = new MyClass(3,4,"five")
let b = new MyClass(a, y=44) // clone a but change y
C# client code:
var m = new MyClass(3, 4, "five");
var m2 = new MyClass(m, y:Util.Some(44)); // clone m but change y
That is, optional parameters are a nice way to do this, and while C# optional parameters have some limitations, you can expose F# optional parameters in a way that works ok with C#, as suggested above.
F# Record types have a built in way of doing exactly what you're asking:
type Vector = {X:float; Y:float}
let v1 = {X=1.; Y=2.}
let v2 = {v1 with X=3.}
How that interops with C#, I'm not sure (edit: see Brian's comment).
Vector will be immutable from any .NET language, since X and Y are implemented as getters without setters.
精彩评论