【问题标题】:Initializing class instance similar to records in F#初始化类实例,类似于 F# 中的记录
【发布时间】:2015-01-18 20:17:11
【问题描述】:

使用 F# 中的记录类型,您可以使用如下语法来基于另一个记录来初始化记录:

let rr3 = { defaultRecord1 with field2 = 42 }

对于非记录类型也有类似的简洁和优雅的东西吗?

我正在使用 C# 类并调用它们的 Clone() 方法并使用 <- 运算符对其属性进行赋值似乎有点不对劲。我还发现了这篇关于 object expressions 的文章,但它似乎不是我想要的。

编辑:总而言之,我试图在我的 F# 代码中实例化 C# 类,我想知道是否有一些简洁的语法可以根据另一个对象的值创建一个类的对象,就像在F# 使用 with 关键字。

【问题讨论】:

    标签: .net f#


    【解决方案1】:

    您实际上可以在方法调用中使用可设置属性,就好像它们是命名参数一样。因此,如果您的类是使用返回原始类型的专用 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!
    

    【讨论】:

      猜你喜欢
      • 2021-05-31
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 2013-04-14
      • 1970-01-01
      相关资源
      最近更新 更多