使用扩展方法覆盖F#中的静态属性

时间:2017-07-28 00:54:52

标签: f#

F#扩展方法可以在与现有实例和静态方法具有相同名称和类型签名的类型上定义,以有效地覆盖这些方法的默认实现,但是我不能让它在静态属性上工作。

特别是,我正在尝试为DateTime创建一个扩展方法,该方法返回更精确的时间,如下所示:

#nowarn "51"

open System

module DateTimeExtensions =

    open System.Runtime.InteropServices

    [<DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi)>]
    extern void private GetSystemTimePreciseAsFileTime(int64*)

    type System.DateTime with
        // example showing that static methods can be overridden
        static member IsLeapYear(_: DateTime) =
            printfn "Using overridden IsLeapYear!"
            true

        // more accurate UtcNow method (note: not supported by older OS versions)
        static member UtcNow =
            printfn "Using overridden UtcNow!"
            let mutable fileTime = 0L
            GetSystemTimePreciseAsFileTime(&&fileTime)
            DateTime.FromFileTimeUtc(fileTime)

然而,执行时的输出

open DateTimeExtensions
let _ = DateTime.IsLeapYear(DateTime.UtcNow)

只是

Using overridden IsLeapYear!

表明静态方法'override'正在工作,但不是静态属性。

(注意:我正在使用F#4.0)

1 个答案:

答案 0 :(得分:3)

这句话似乎不正确:

  

可以在具有相同名称和的类型上定义F#扩展方法   类型签名作为现有实例和静态方法有效   覆盖这些方法的默认实现,但我不能   让它在静态属性上工作。

不,他们不会覆盖。

你可能会感到困惑,因为事实上你的IsLeapYear签名是错误的,它应该是一个整数,这就是为什么它起作用我的意思是你没有覆盖任何东西,只是添加一个新的(扩展)方法。

如果您使用原始签名进行尝试,您会发现它也不起作用:

type System.DateTime with
    // example showing that static methods can NOT be overridden
    static member IsLeapYear(_: int) =
        printfn "Using overridden IsLeapYear!"
        false

> DateTime.IsLeapYear(2000);;
val it : bool = true

这与静态属性扩展的行为一致。

无论如何,我不确定为什么决定不覆盖,如果在设计语言时有这样的决定。我认为这将是一个有趣的功能,如果有充分的理由不实现它,至少应该发出一个警告说,因为该方法已经存在,它永远不会被调用。

也许我会为F#编译器打开一个问题或建议。