我正在开发一个程序,用户可以在运行时向我发送各种对象,并且我不事先知道它们的类型(在编译时)。当对象可以向下转换为元素类型为[[any的(F#)数组时,我想对基础数组执行一些常规操作。例如。 Array.Length
,Array.sub
...
box [| 1; 2; 3 |]
或box [| "a"; "b"; "c" |]
或任何'a[]
之类的东西,但在编译时我不知道'a
。以下内容无效:
let arrCount (oarr: obj) : int =
match oarr with
| :? array<_> as a -> a.Length
| :? (obj[]) as a -> a.Length
// | :? (int[]) as a -> a.Length // not an option for me here
// | :? (string[]) as a -> a.Length // not an option for me here
// | ...
| _ -> failwith "Cannot recognize an array"
例如arrCount (box [| 1; 2; 3 |])
和arrCount (box [| "a"; "b"; "c" |])
都在这里失败。到目前为止,我发现的唯一解决方案是使用反射,例如:
type ArrayOps = static member count<'a> (arr: 'a[]) : int = arr.Length static member sub<'a> (arr: 'a[]) start len : 'a[] = Array.sub arr start len // ... let tryCount (oarr: obj) = let ty = oarr.GetType() if ty.HasElementType && ty.BaseType = typeof<System.Array> then let ety = ty.GetElementType() let meth = typeof<ArrayOps>.GetMethod("count").MakeGenericMethod([| ety |]) let count = meth.Invoke(null, [| oarr |]) :?> int Some count else None
我的问题:有没有办法在不使用反射的情况下对形式为Array.count
的参数使用Array.sub
,box [| some elements of some unknown type |]
等函数?
array<_>
无效,因为从F#的角度来看,array<obj>
不等于array<int>
等,这意味着您必须检查每种协变类型。