[英]converting an enum to a list or sequence or generic collection type in F#
I have a type that is either a Dictionary<string,Node<'a>>*Edge<'a> list
or a ConcurrentDictionary<string,Node<'a>>*Edge<'a> list
.我有一个类型是
Dictionary<string,Node<'a>>*Edge<'a> list
或ConcurrentDictionary<string,Node<'a>>*Edge<'a> list
。 I am trying to create a get_nodes
function, but when I call .Values
from the Dictionary
and the ConcurrentDictionary
, the functions return different types!我正在尝试创建一个
get_nodes
函数,但是当我从Dictionary
和ConcurrentDictionary
调用.Values
时,这些函数返回不同的类型!
So I need to somehow convert both of the types into the same type for F# to compile...所以我需要以某种方式将这两种类型转换为相同的类型,以便 F# 编译...
The type given by Dictionary.Values
is Dictionary'2.ValueCollection<string,Node<'a>>
while the type yielded by ConcurrentDictionary
is ICollection<Node<'a>>
. Dictionary.Values
给出的类型是Dictionary'2.ValueCollection<string,Node<'a>>
而ConcurrentDictionary
产生的类型是ICollection<Node<'a>>
。
I figured out that both types have a "GetEnumerator()" function.我发现这两种类型都有一个“GetEnumerator()”函数。 What I need to do is somehow turn the enumerator into a seq or list, etc.
我需要做的是以某种方式将枚举器转换为 seq 或列表等。
Here is my code:这是我的代码:
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()
How do I pull the data out of the enum variable?如何从枚举变量中提取数据?
You are probably used to C# which would auto upcast the ValueCollection to an ICollection (which ValueCollection implements).您可能已经习惯了 C#,它会自动将 ValueCollection 向上转换为 ICollection(ValueCollection 实现)。 F# does not do this, so you must manually cast the result of Dictionary.Values to ICollection.
F# 不会这样做,因此您必须手动将 Dictionary.Values 的结果转换为 ICollection。
let n = nd.Values :> ICollection<Node<'a>>
Full method would look something like this:完整方法看起来像这样:
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
From what I understand, F# does not auto-upcast because of the way that the auto type inference engine works.据我了解,由于自动类型推理引擎的工作方式,F# 不会自动向上转换。 It's irritating when you're used to C#, but it's a price worth paying to get automatic type inferencing.
当您习惯了 C# 时,这很烦人,但为了获得自动类型推断而付出的代价是值得的。 Also consider that in C#, you would have to specify the return type up front on the method, which makes it easy for C# to do the cast for you.
还要考虑到,在 C# 中,您必须在方法的前面指定返回类型,这使得 C# 可以轻松地为您进行转换。 F# engine infers the return type based on what you actually return, so the safest thing is to not make assumptions about how you want it cast.
F# 引擎根据您实际返回的内容推断返回类型,因此最安全的做法是不要假设您希望它如何转换。
Not general consensus, but my opinion: I hope they will add auto upcasting of return values for specific cases (like output type is declared ahead of time or to make branches conform like above), but it's a minor irritation for now.不是普遍共识,但我的意见是:我希望他们会为特定情况添加返回值的自动向上转换(例如提前声明输出类型或使分支符合上述要求),但现在这是一个小问题。
Update (from question in comments)更新(来自评论中的问题)
ICollection<T>
should now be directly usable as a sequence since it implements IEnumerable<T>
. ICollection<T>
现在应该可以直接用作序列,因为它实现了IEnumerable<T>
。 In this case auto-upcasting actually does work.在这种情况下,自动向上转换实际上确实有效。 :)
:)
myGraph
|> Graph.get_nodes
|> Seq.iter (fun x -> printfn "%A" x)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.