6

有没有办法通过反射来确定给定的类型参数是否满足 F# 比较约束?

我怀疑不是,因为表达式

typedefof<Set<_>>.MakeGenericType [| typeof<System.Type> |]

似乎没有产生任何错误。不过,我还是想听听一些权威的意见。

4

1 回答 1

8

引用 Don Syme关于平等和比较约束的详尽帖子

约束类型 : 比较在以下情况下成立:

  • 如果类型是命名类型,则类型定义没有NoComparison属性;和
  • 类型定义实现System.IComparable;和
  • 该类型的任何“比较依赖项”也满足ty i:比较

约束'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
于 2013-01-15T15:11:22.987 回答