mpeac
mpeac

Reputation: 750

Overriding static properties in F# with extension methods

F# extension methods can be defined on types with the same name and type signature as existing instance and static methods to effectively override the default implementation of these methods, however I can't get this to work on static properties.

In particular, I'm trying to create an extension method for DateTime that returns a more precise time as follows:

#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)

However, the output when executing

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

is just

Using overridden IsLeapYear!

which shows that the static method 'override' is working, but not the static property.

(Note: I'm using F# 4.0)

Upvotes: 2

Views: 377

Answers (1)

Gus
Gus

Reputation: 26174

This statement seems to be incorrect:

F# extension methods can be defined on types with the same name and type signature as existing instance and static methods to effectively override the default implementation of these methods, however I can't get this to work on static properties.

No, they don't override.

You might be confused because in fact your signature of IsLeapYear is wrong, it should take an integer, that's why it works I mean you are not overriding anything, just adding a new (extension) method.

If you try it with the original signature you'll see that it doesn't work either:

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

Which is consistent with the behavior of the static property extension.

Anyway I'm not sure why it was decided not to override, if there was such decision at all when designing the language. I think it would be an interesting feature and if there is a good reason not to implement it at least it should emit a warning saying that since the method already exists it will never be called.

Maybe I will open an issue or a suggestion for the F# compiler.

Upvotes: 3

Related Questions