我刚刚开始使用F#,而且关于投射的一些问题让我非常困惑 . 不幸的是,我的背景阅读试图弄清楚为什么让我更加困惑,所以我正在寻找一些具体的答案,我可以适应一般的解释......
我有一个由此函数生成的枚举的ReadOnlyCollection <'T>:
let GetValues<'T when 'T :> Enum> () =
(new ReadOnlyCollection<'T>(Enum.GetValues (typeof<'T>) :?> 'T[])) :> IList<'T>
我想要做的是找到其值所使用的枚举的所有位(即,按位或列表中的所有值),并将其作为通用枚举类型返回,'T . 这样做的显而易见的方法似乎是:
let UsedBits<'T when 'T :> Enum> () =
GetValues<'T>()
|> Seq.fold (fun acc a -> acc ||| a) 0
...除了无法编译之外,错误“此处不能使用声明的类型参数'T',因为在编译时无法解析类型参数 . ”
我可以通过首先转换为Int32来完成实际的工作(我真的不想这样做,因为我希望这个函数适用于所有枚举而不管底层类型),即:
let UsedBits<'T when 'T :> Enum> () =
GetValues<'T>()
|> Seq.map (fun a -> Convert.ToInt32(a))
|> Seq.fold (fun acc a -> acc ||| a) 0
...但是然后结果产生为Int32 . 如果我尝试将其强制转换为'T,我再次遇到编译错误 .
我不想在我的问题中过于具体,因为我认为这种方法存在缺陷吗?我该怎么办呢?
(Edited to add: ,发布@ Daniel的回答
唉,这似乎是我不能理解上下文以便理解答案的情况之一,所以...
我想我理解内联和不同的约束在你的答案中做了什么,但作为一个F#新手,你是否会介意对这些事情进行一些扩展,以便我可以检查一下我的理解是不是基于什么?谢谢 .
)
1 回答
你可以这样做:
inline
允许更灵活的约束,即'T (requires member ( ||| ))
. 没有它,编译器必须选择可以用IL表示的约束,或者,如果不能这样做,则选择具体类型 . 在这种情况下,它选择int
,因为它支持(|||)
.这是一个更简单的复制品:
有关详细信息,请参阅MSDN上的Statically Resolved Type Parameters .