您实际上可以在方法调用中使用可设置属性,就好像它们是命名参数一样。因此,如果您的类是使用返回原始类型的专用 Clone 方法实现的:
type Foo() =
member val X = 0 with get, set
member val Y = 0 with get, set
member this.Clone() = new Foo(X = this.X, Y = this.Y)
interface System.ICloneable with
member this.Clone() = box (this.Clone())
那么您将能够执行以下操作:
let foo1 = new Foo(X = 1, Y = 2)
let foo2 = foo1.Clone(X = 3)
但很可能您的课程只有 ICloneable 实现。在这种情况下,上述技巧不会开箱即用,因为ICloneable.Clone 返回的obj 没有可设置的X 属性。幸运的是,您可以将所需的方法添加为扩展:
/// Original class
type Foo() =
member val X = 0 with get, set
member val Y = 0 with get, set
interface System.ICloneable with
member this.Clone() = box (new Foo(X = this.X, Y = this.Y))
let foo1 = new Foo(X = 1, Y = 2)
let foo2 = foo1.Clone(X = 3) // error FS0039: The field, constructor or member 'Clone' is not defined
let foo3 = (foo1 :> System.ICloneable).Clone(X = 3) // error FS0495: The member or object constructor 'Clone' has no argument or settable return property 'X'. The required signature is System.ICloneable.Clone() : obj.
/// Extension that makes the above trick work
type Foo with
member this.Clone() = (this :> System.ICloneable).Clone() :?> Foo
let foo1 = new Foo(X = 1, Y = 2)
let foo2 = foo1.Clone(X = 3) // works!