2012-08-06 150 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