2017-07-28 116 views
2

F#擴展方法可以在與現有實例和靜態方法具有相同名稱和類型簽名的類型上定義,以便有效地覆蓋這些方法的默認實現,但是我無法獲得此內容在靜態屬性上工作。執行使用擴展方法覆蓋F#中的靜態屬性

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

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

然而,輸出只是

特別是,我試圖爲DateTime返回一個更精確的時間創建的擴展方法如下

Using overridden IsLeapYear! 

它表明靜態方法'覆蓋'正在工作,bu不是靜態屬性。

(注:我使用F#4.0)

+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#編譯器提出一個問題或建議。

+1

您確實打開了一個問題,或者至少打開了討論:https://github.com/Microsoft/visualfsharp/pull/3582#issuecomment-333663962 – Abel