我的类型是Dictionary<string,Node<'a>>*Edge<'a> list
or a ConcurrentDictionary<string,Node<'a>>*Edge<'a> list
。我正在尝试创建一个get_nodes
功能,但是当我打电话时.Values
来自Dictionary
和ConcurrentDictionary
,函数返回不同的类型!
所以我需要以某种方式将这两种类型转换为相同的类型,以便 F# 进行编译...
给出的类型Dictionary.Values
is Dictionary'2.ValueCollection<string,Node<'a>>
而产生的类型ConcurrentDictionary
is ICollection<Node<'a>>
.
我发现这两种类型都有一个“GetEnumerator()”函数。我需要做的是以某种方式将枚举器转换为 seq 或列表等。
这是我的代码:
static member get_nodes (g:Graph<'a>) =
match g with
| Dictionary_Graph(nd,el) -> let n = nd.Values
let enum = n.GetEnumerator()
| ConcurrentDictionary_Graph(nd,el) -> let n = nd.Values
let enum = n.GetEnumerator()
如何从枚举变量中提取数据?
您可能习惯使用 C#,它会自动将 ValueCollection 向上转换为 ICollection(由 ValueCollection 实现)。 F# 不会执行此操作,因此您必须手动将 Dictionary.Values 的结果转换为 ICollection。
let n = nd.Values :> ICollection<Node<'a>>
完整的方法看起来像这样:
static member get_nodes (g:Graph<'a>) =
match g with
| Dictionary_Graph(nd,el) ->
nd.Values :> ICollection<Node<'a>>
| ConcurrentDictionary_Graph(nd,el) ->
nd.Values
据我了解,由于自动类型推理引擎的工作方式,F# 不会自动向上转型。当您习惯使用 C# 时,这会很烦人,但为了获得自动类型推断,这是值得付出的代价。还要考虑到,在 C# 中,您必须预先在方法上指定返回类型,这使得 C# 可以轻松地为您进行转换。 F# 引擎根据您实际返回的内容推断返回类型,因此最安全的做法是不要假设您希望它如何转换。
不是普遍共识,而是我的观点:我希望他们会为特定情况添加返回值的自动向上转换(例如提前声明输出类型或使分支符合上面的要求),但目前这是一个小刺激。
Update(来自评论中的问题)
ICollection<T>
现在应该可以直接用作序列,因为它实现了IEnumerable<T>
。在这种情况下,自动向上转换实际上起作用了。 :)
myGraph
|> Graph.get_nodes
|> Seq.iter (fun x -> printfn "%A" x)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)