有没有办法通过反射来确定给定的类型参数是否满足 F# 比较约束?
我怀疑不是,因为表达式
typedefof<Set<_>>.MakeGenericType [| typeof<System.Type> |]
似乎没有产生任何错误。不过,我还是想听听一些权威的意见。
有没有办法通过反射来确定给定的类型参数是否满足 F# 比较约束?
我怀疑不是,因为表达式
typedefof<Set<_>>.MakeGenericType [| typeof<System.Type> |]
似乎没有产生任何错误。不过,我还是想听听一些权威的意见。
引用 Don Syme关于平等和比较约束的详尽帖子:
约束类型 : 比较在以下情况下成立:
约束'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