F#无反射的向下转换数组

问题描述 投票:0回答:2

我正在开发一个程序,用户可以在运行时向我发送各种对象,并且我不事先知道它们的类型(在编译时)。当对象可以向下转换为元素类型为[[any的(F#)数组时,我想对基础数组执行一些常规操作。例如。 Array.LengthArray.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.subbox [| some elements of some unknown type |]等函数?
arrays f# downcast
2个回答
1
投票
[奇怪的是,这在C#和VB等语言中不是问题,尽管您可能需要为F#做一些额外的工作。一般来说,您不能这样做,因为F#没有协变类型。

0
投票
由于F#是静态类型安全的,因此它会尝试阻止您执行此操作,因此这并不容易。将其强制转换为array<_>无效,因为从F#的角度来看,array<obj>不等于array<int>等,这意味着您必须检查每种协变类型。
© www.soinside.com 2019 - 2024. All rights reserved.