我希望匹配" obj"类型的对象obj1。根据其实际类型。 问题是列表类型的类型检查模式(下例中的第二个)与F#列表不匹配。
let obj1 = [1;2;3] :> obj
match obj1 with
| :? System.Array as a -> printfn "it's an array: %A" a
| :? List<_> as l -> printfn "It's a list: %A" l
| _ -> printfn "other type"
输出&#34;其他类型&#34;,虽然我希望它是&#34;它是一个列表:[1; 2; 3]&#34;
如何正确检查列表类型?
答案 0 :(得分:3)
obj : [any type]
您需要做的是区分您的obj是否为泛型类型。通过.GetType()
获取它的类型,你会找到合适的属性。
obj : [some type of the form T<'T1, 'T2, ..., 'Tn> for concrete types T1, T2, ..., Tn]
如果是,那么通过使用.GetType()
obj : [some type of the form T<'T1, 'T2, ..., 'Tn> with T1, T2, ..., Tn not bound yet]
此类型您现在可以与typedefof<_ list>
进行比较(_ list
被推断为obj list
,但typedefof
与typeof
相对于let ty = obj.GetType()
match obj with
| unknownType when not ty.IsGenericType -> "some non-generic type, probably a concrete collection"
| list when ty.GetGenericTypeDefinition() = typedefof<_ list> -> "list"
| array when ty.GetGenericTypeDefinition() = typedefof<_ array> -> "array"
| _ -> "something else, i.e. a generic type that we don't know"
你的通用类型定义)。
最终代码看起来像这样(伪代码)
apt-get install <service-name>
答案 1 :(得分:2)
Daniel Fabian已经在他的回答中解释了这个问题。
实现其解决方案的一种方法是使用Active Pattern:
let (|IsList|_|) (candidate : obj) =
let t = candidate.GetType()
if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<list<_>>
then Some (candidate :?> System.Collections.IEnumerable)
else None
您现在可以更改匹配项以使用此活动模式:
let obj1 = [1;2;3] :> obj
match obj1 with
| :? System.Array as a -> printfn "it's an array: %A" a
| IsList l -> printfn "It's a list: %A" l
| _ -> printfn "other type"
打印:
> It's a list: [1; 2; 3]
答案 2 :(得分:-2)
我不打电话给List&lt; _&gt;作为F#列表 - 它是.NET框架类型。您可以将它与(int list)类型匹配 - 它是F#list:
match obj1 with | :? (int list) as l -> 1 | _ -> 0