I am working on a program where the user can send me all sort of objects at runtime, and I do not know their type in advance (at compile time). When the object can be down-cast to an (F#) array, of any element type, I would like to perform some usual operations on the underlying array. E.g. Array.Length
, Array.sub
...
The objects I can get from the users will be of things like box [| 1; 2; 3 |]
or box [| "a"; "b"; "c" |]
, or any 'a[]
, but I do not know 'a
at compile time.
The following does not work :
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"
E.g both arrCount (box [| 1; 2; 3 |])
and arrCount (box [| "a"; "b"; "c" |])
fail here.
The only solution I found so far is to use reflection, e.g. :
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
My question: is there a way to use functions such as Array.count
, Array.sub
, etc... on arguments of the form box [| some elements of some unknown type |]
without using reflection?