有没有办法通过反射确定给定的类型参数是否满足F#比较约束?
我怀疑没有,因为表达式
typedefof<Set<_>>.MakeGenericType [| typeof<System.Type> |]
似乎没有错误。不过,我想听听一些权威的意见。
答案 0 :(得分:6)
引用Don Syme的全面post on equality and comparison constraints:
约束类型:比较在以下情况下成立:
约束'T when 'T :> IComparable
可以在CIL中编码并反映,但'T when 'T : comparison
都不是。
由于这两个约束不相等,因此使用comparable
约束标记IComparable
类型有点误导,因为它无法使用反射来区分两者。
equality
约束与IEquatable<_>
之间存在类似的关系。
修改
Jack提到comparison
约束可以用F#元数据编码,这促使我查看PowerPack中的元数据阅读器。它可用于检测约束:
open Microsoft.FSharp.Metadata
let setEntity = FSharpAssembly.FSharpLibrary.GetEntity("Microsoft.FSharp.Collections.FSharpSet`1")
for typeArg in setEntity.GenericParameters do
printfn "%s - comparison=%b"
typeArg.Name
(typeArg.Constraints |> Seq.exists (fun c -> c.IsComparisonConstraint))
这是一个人为的例子,显示了实施IComparable
和满足comparison
之间的差异:
type A() =
interface IComparable with
member __.CompareTo(_) = 0
[<NoComparison>]
type B() =
inherit A()
type C<'T when 'T : comparison>() = class end
type D<'T when 'T :> IComparable>() = class end
let c = C<B>() //ERROR
let d = D<B>() //OK