【问题标题】:F# Generic IDictionary extension failedF# 通用 IDictionary 扩展失败
【发布时间】:2016-06-30 09:58:02
【问题描述】:

当我尝试使用以下代码扩展 IDictionary 时

type Generic.IDictionary<'TKey, 'TValue> with
    member this.GetOrAdd (key:'TKey, fun':'TKey -> 'TValue) =
        match this.ContainsKey(key) with
        | true -> this.Item(key)
        | false -> 
            let val_ = fun' key
            this.Add(key, val_)
            val_

let dd = dict[(1,2); (3,4)]
let f = fun x -> 2*x
let d5 = dd.GetOrAdd(5, f)

我在运行时遇到以下错误。

System.NotSupportedException:引发类型 >'System.NotSupportedException' 的异常。 在 Microsoft.FSharp.Core.ExtraTopLevelOperators.dictValueType@98.System->Collections-Generic-IDictionary2-Add(TKey key, T value) at FSI_0011.IDictionary2.GetOrAdd[TKey,TValue](IDictionary2 this, &gt;TKey key, FSharpFunc2 fun') 在 >D:\BaiduYunDownload\DroiEtl\ Droi.MyToPG\Util.Sync.fs:第 259 行 在 .$FSI_0018.main@() in >D:\BaiduYunDownload\DroiEtl\Droi.MyToPG\Util.Sync.fs:line 264 由于错误而停止

但是编译器在构建时不会抱怨... 请帮帮我...

【问题讨论】:

  • 使用TryGetValue 而不是ContainsKey 会稍微快一些,因为“已经存在”的代码路径只需要进行一次字典查找,而不是您现在正在执行的两次查找.

标签: f# f#-3.0


【解决方案1】:

dict is documented 返回一个只读 IDictionary&lt;_,_&gt; - 然后你在它上面调用.Add,支持类正确地抛出一个异常。

创建一个真正的 Dictionary 实例,您会看到它按预期工作:

open System.Collections.Generic

type IDictionary<'TKey, 'TValue> with
    member this.GetOrAdd (key:'TKey, fun':'TKey -> 'TValue) =
        match this.ContainsKey key with
          | true  -> this.Item key
          | false -> let val' = fun' key
                     this.Add (key, val')
                     val'

let dd =
    let d = Dictionary()
    d.Add (1, 2)
    d.Add (3, 4)
    d

printfn "%A" dd
dd.GetOrAdd (5, (fun x -> 2 * x)) |> printfn "%A :: %d" dd
dd.GetOrAdd (5, (fun x -> 9 * x)) |> printfn "%A :: %d" dd

输出:

seq [[1, 2]; [3, 4]]
seq [[1, 2]; [3, 4]; [5, 10]] :: 10
seq [[1, 2]; [3, 4]; [5, 10]] :: 10

Online Demo

在实施方面,@JoelMueller 的建议是一个明显的改进:

type IDictionary<'TKey, 'TValue> with
    member this.GetOrAdd (key:'TKey, fun':'TKey -> 'TValue) =
        match this.TryGetValue key with
          | true, val' -> val'
          | false, _   -> let val' = fun' key
                          this.Add (key, val')
                          val'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    • 2014-12-20
    • 2012-05-20
    • 1970-01-01
    相关资源
    最近更新 更多