F# Generic IDictionary 扩展失败
F# Generic IDictionary extension failed
当我尝试使用以下代码扩展 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: Exception of type >'System.NotSupportedException' was thrown.
at Microsoft.FSharp.Core.ExtraTopLevelOperators.dictValueType@98.System->Collections-Generic-IDictionary2-Add(TKey key, T value)
at FSI_0011.IDictionary
2.GetOrAdd[TKey,TValue](IDictionary2 this, >TKey key, FSharpFunc
2 fun') in >D:\BaiduYunDownload\DroiEtl\Droi.MyToPG\Util.Sync.fs:line 259
at .$FSI_0018.main@() in >D:\BaiduYunDownload\DroiEtl\Droi.MyToPG\Util.Sync.fs:line 264
Stopped due to error
但是编译器在编译时并没有报错...
请帮助我...
dict
is documented to return a read-only IDictionary<_,_>
– 然后调用 .Add
它,并且支持 class 正确地抛出异常。
改为创建一个真实的 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
在实施方面,@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'
当我尝试使用以下代码扩展 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: Exception of type >'System.NotSupportedException' was thrown. at Microsoft.FSharp.Core.ExtraTopLevelOperators.dictValueType@98.System->Collections-Generic-IDictionary
2-Add(TKey key, T value) at FSI_0011.IDictionary
2.GetOrAdd[TKey,TValue](IDictionary2 this, >TKey key, FSharpFunc
2 fun') in >D:\BaiduYunDownload\DroiEtl\Droi.MyToPG\Util.Sync.fs:line 259 at .$FSI_0018.main@() in >D:\BaiduYunDownload\DroiEtl\Droi.MyToPG\Util.Sync.fs:line 264 Stopped due to error
但是编译器在编译时并没有报错... 请帮助我...
dict
is documented to return a read-only IDictionary<_,_>
– 然后调用 .Add
它,并且支持 class 正确地抛出异常。
改为创建一个真实的 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
在实施方面,@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'