我有这个 F# 类
module File1
open System
open System.Collections.Generic
type TimeRangeList<'e>(getter: DateTime * DateTime -> List<'e>, ?maybe_tFrom: DateTime, ?maybe_tTo: DateTime) as this =
inherit List<'e>()
//inherit List<'e>(getter(defaultArg maybe_tTo DateTime.Now, defaultArg maybe_tFrom ((defaultArg maybe_tTo DateTime.Now).AddDays(-1.0))))
let tTo = defaultArg maybe_tTo DateTime.Now
let tFrom = defaultArg maybe_tFrom (tTo.AddDays(-1.0))
do this.AddRange(getter(tFrom, tTo))
现在我想添加构造函数并使用 here 中的语法
type TimeRangeList<'e> =
inherit List<'e>
val tFrom: DateTime
val tTo: DateTime
new (getter: DateTime * DateTime -> List<'e>, ?maybe_tFrom: DateTime, ?maybe_tTo: DateTime) = {
inherit List<'e>()
//inherit List<'e>(defaultArg maybe_tFrom ((defaultArg maybe_tTo DateTime.Now).AddDays(-1.0)), getter(defaultArg maybe_tTo DateTime.Now))
tTo = defaultArg maybe_tTo DateTime.Now
tFrom = defaultArg maybe_tFrom (tTo.AddDays(-1.0)) //tTo undefined
//tFrom = defaultArg maybe_tFrom ((defaultArg maybe_tTo DateTime.Now).AddDays(-1.0))
}
do this.AddRange(getter(tFrom, tTo)) //primary constructor required
这段代码给出了两个错误:
- 在“tFrom=...”中它说“tTo 未定义”,而 tTo 显然在 范围;作为一种解决方法,我可以重复 defaultArg 调用,如图所示 以下(注释)行。有没有更好的方法?
- 在调用 'AddRange' 的最后一行,它提示 do 调用只能在主构造函数中执行,这是公平的。但是,如何调用必要的 AddRange 来初始化列表?我尝试了不同的选择,但找不到方法。在注释的继承行中显示了一种解决方法,但最后我重复且冗余地调用 defaultArg;一定有更清晰更优雅的方式
最佳答案
这是您正在寻找的语法:
module File1
open System
open System.Collections.Generic
type TimeRangeList<'e> =
inherit List<'e>
val tFrom: DateTime
val tTo: DateTime
new (getter: DateTime * DateTime -> List<'e>, ?maybe_tFrom: DateTime, ?maybe_tTo: DateTime) as this =
let to_ = defaultArg maybe_tTo DateTime.Now
let from_ = defaultArg maybe_tFrom (to_.AddDays(-1.0))
{
inherit List<'e>()
tTo = to_
tFrom = from_
}
then
this.AddRange(getter(this.tFrom, this.tTo))
文档链接:
- 在其他构造函数中,use the
then
keyword instead ofdo
- 在附加构造函数中为实例定义自引用名称,put
as this
after thenew()
expression
稍微解释一下,{ field = value; field2 = value2 }
语法不必是在定义辅助构造函数的 new()
block 中找到的唯一表达式。它必须是 last 表达式,即返回的表达式。 (这里,即使从技术上讲 then
block 是构造函数中的“最后一个” block ,它的返回值(必须是 unit
)被忽略并且实际返回构造函数的值是最后一个表达式在 then
block 中找不到)。因此,较早使用 let
表达式来定义要放入类字段的值是安全的,并且这些 let
表达式可以像在正常情况下一样相互引用代码。因此,如果您需要在多个字段中进行复杂或昂贵的计算,您可以这样做:
new () =
let result = expensiveCalculationIWantToDoOnlyOnce()
{ field1 = result; field2 = result + 1; field3 = result + 2 }
关于inheritance - 具有多个构造函数语法的 F# 继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51094049/