F#中的C#对象初始化语法

请注意:这个问题与这个问题一样。

我最近遇到了一些我之前没有遇到过的C#语法:

有没有办法在F#中做到这一点?

class Two { public string Test { get; set; } } class One { public One() { TwoProperty = new Two(); } public Two TwoProperty { get; private set; } } var test = new One(){ TwoProperty = { Test = "Test String" }}; 

(注意当setter是私有时初始化器中的TwoProperty的初始化 – 它在存储在TwoProperty的对象上设置属性,但TwoProperty属性中存储新的Two实例)

编辑:我最近在monotouch的构造函数中遇到了一些C#代码,如下所示:

 nameLabel = new UILabel { TextColor = UIColor.White, Layer = { ShadowRadius = 3, ShadowColor = UIColor.Black.CGColor, ShadowOffset = new System.Drawing.SizeF(0,1f), ShadowOpacity = .5f } }; 

我能想出的最好的F#翻译是这样的:

 let nameLabel = new UILabel ( TextColor = UIColor.White ) do let layer = nameLabel.Layer layer.ShadowRadius <- 3.0f layer.ShadowColor <- UIColor.Black.CGColor layer.ShadowOffset <- new System.Drawing.SizeF(0.0f,1.0f) layer.ShadowOpacity <- 0.5f 

这并不可怕,但它确实有更多的噪音与重复的layer参考加上更多的命令和更少的声明。

将构造封装到单独的初始化函数中是否有意义?

 let layerInit layer radius color offset opacity = do layer.ShadowRadius <- radius layer.ShadowColor <- color layer.ShadowOffset <- offset layer.ShadowOpacity <- opacity layer // I do this in case you want to use this fluently or pass in new Layer() 

然后在你的代码中使用它:

 let nameLabel = new UILabel ( TextColor = UIColor.White ) layerInit nameLabel.Layer 3.0f UIColor.Black.CGColor new System.Drawing.SizeF(0.0f,1.0f) 0.5f |> ignore 

我不认为F#允许在初始化期间设置嵌套属性。 假设您是API的作者,解决方法是将整个对象传递给构造函数。 这消除了对具有不同可访问性的getter和setter的需求,并使整个F#代码更加清晰。

 type Two() = member val Test = "" with get, set type One(twoProperty) = member val TwoProperty = twoProperty let test = One(Two(Test="foo")) 

正如您在评论中提到的,您可以创建一个辅助函数,接受各种属性作为可选参数。 类型扩展适用于此:

 type UILayer with member this.Configure(?shadowRadius, ?shadowColor, ?shadowOffset, ?shadowOpacity) = this.ShadowRadius <- defaultArg shadowRadius this.ShadowRadius this.ShadowColor <- defaultArg shadowColor this.ShadowColor this.ShadowOffset <- defaultArg shadowOffset this.ShadowOffset this.ShadowOpacity <- defaultArg shadowOpacity this.ShadowOpacity let nameLabel = UILabel(TextColor=UIColor.White) nameLabel.Layer.Configure( shadowRadius=3.0f, shadowColor=UIColor.Black.CGColor, shadowOffset=SizeF(0.0f, 1.0f), shadowOpacity=0.5f) 

F#4.0推出了一个function,可能有助于封装@plinth的答案。 它允许创建扩展属性,可以在构造函数中初始化。