F#类型约束和反射 [英] F# type constraints and reflection
问题描述
是否可以通过反射确定给定类型参数是否满足F#比较约束?
Is there any way to determine whether a given type parameter satisfies the F# comparison constraint through reflection?
我怀疑不是,因为该表达方式
I would suspect not, since the expression
typedefof<Set<_>>.MakeGenericType [| typeof<System.Type> |]
似乎没有错误.不过,我还是想听听一些权威意见.
appears to yield no errors. Still, I would like to hear some authoritative opinion on this.
推荐答案
Quoting from Don Syme's thorough post on equality and comparison constraints:
约束类型:比较在以下情况下成立
- 如果类型是命名类型,则类型定义不具有 NoComparison 属性;和
- 类型定义实现 System.IComparable ;和
- 任何类型的比较依赖项"也满足 ty i :比较
- if the type is a named type, then the type definition doesn't have the NoComparison attribute; and
- the type definition implements System.IComparable; and
- any "comparison dependencies" of the type also satisfy tyi : comparison
约束'T when 'T :> IComparable
可以在CIL中进行编码并反映出来,而'T when 'T : comparison
都不是真的.
The constraint 'T when 'T :> IComparable
can be encoded in CIL and reflected upon, whereas neither is true of 'T when 'T : comparison
.
由于这两个约束不相等,因此用IComparable
约束标记comparable
类型有点误导,因为这将导致无法使用反射来区分这两个类型.
Since the two constraints are not equivalent, marking comparable
types with the IComparable
constraint is a bit misleading since it would make it impossible to distinguish between the two using reflection.
equality
约束与IEquatable<_>
之间存在相似的关系.
There's a similar relationship between the equality
constraint and IEquatable<_>
.
编辑
Jack提到comparison
约束可以在F#元数据中进行编码,这促使我着眼于PowerPack中的元数据读取器.它可以用来检测约束:
Jack's mention that the comparison
constraint could be encoded in F# metadata prompted me to look at the metadata reader in PowerPack. It can be used to detect the constraint:
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
之间的差异:
Here's a contrived example that shows the disparity between implementing IComparable
and satisfying 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
这篇关于F#类型约束和反射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!