2012-08-06 95 views
1

是否可以將類型約束爲支持null的結構或引用類型?像這個功能假設約束:支持null的結構和引用類型的類型約束

let getOrDefault<'T when ('T : struct) or ('T : null)> (d: IDictionary<_, 'T>) key = 
    match d.TryGetValue(key) with 
    | true, v -> v 
    | _ -> Unchecked.defaultof<'T> 

的功能不應該與F#類型一起使用,除非標有[<AllowNullLiteral>]

回答

2

我不認爲你可以把or之間的兩個約束。 通常當我需要這樣的東西constraint1或constraint2或者...或者constraintN什麼,我要做的就是創建重載:

open System.Collections.Generic 

// unconstrained function 
let getOrDefaultG (d: IDictionary< _ , 'T>) key = 
    match d.TryGetValue(key) with 
    | true, v -> v 
    | _ -> Unchecked.defaultof<'T> 

// individually constrained 
let getOrDefaultS<'K,'T when 'T :struct> (d:IDictionary<'K,'T>) = getOrDefaultG d 
let getOrDefaultN<'K,'T when 'T :null > (d:IDictionary<'K,'T>) = getOrDefaultG d 

// overloads 
type GetOrDefault = GetOrDefault with 
    static member ($) (GetOrDefault, d) = fun dummyArg  -> getOrDefaultS d 
    static member ($) (GetOrDefault, d) = fun (dummyArg:unit) -> getOrDefaultN d 

// the desired function 
let inline getOrDefault d key = (GetOrDefault $ d)() key 

注:dummyArg是一招我用它來創建兩個不同的簽名,並把它編譯。

+0

如果你有兩個以上的重載,你將如何處理'dummyArg'? – Daniel 2012-08-07 22:00:33

+0

好問題!我會添加另一個名爲dummyArg2的參數,然後在第一次重載時,我將根本不會輸入任何類型,僅次於dummyArg1,而第三次輸入兩者。我不明白爲什麼我必須做這些技巧。簽名不同(錯誤?)。 – Gustavo 2012-08-07 23:17:51