Это будет выглядеть одинаково независимо от того, является ли это C # или F #.
Вы говорите "в C # это займет легкую работу", но я думаю, что cmon
Vector WithX(float x) { return new Vector(x, this.Y); }
это правда?
Как в C #, так и в F #, чтобы предотвратить присвоение свойству X, вы создаете свойство с помощью «getter», но без «setter».
Я думаю, вы делаете все это сложнее, чем оно есть, или, может быть, я неправильно понимаю, о чем вы спрашиваете.
EDIT
Для (я думаю, редкого) случая, когда имеется 20 полей, и вы можете изменить только небольшое их произвольное подмножество, я нашел симпатичный хак, чтобы красиво использовать вместе необязательные параметры F # и C #.
F # Код:
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 # код клиента:
let a = new MyClass(3,4,"five")
let b = new MyClass(a, y=44) // clone a but change y
C # код клиента:
var m = new MyClass(3, 4, "five");
var m2 = new MyClass(m, y:Util.Some(44)); // clone m but change y
То есть необязательные параметры - хороший способ сделать это, и, хотя необязательные параметры C # имеют некоторые ограничения, вы можете выставлять необязательные параметры F # таким образом, который работает нормально с C #, как предложено выше.