对F#度量单位的反思

目前已在F#中添加了对reflection的支持,但它不适用于度量类型。 是否可以在F#中使用reflection来测量类型? 我读过这个 。 那是在2008年,但是如果你在ildasm中检查一些像bellow这样的代码,你就看不到任何关于Units of Measure

 // Learn more about F# at http://fsharp.net [] type m [] type cm let CalculateVelocity(length:float ,time:float) = length / time 

ildasm输出:

 .method public static float64 CalculateVelocity(float64 length, float64 time) cil managed { // Code size 5 (0x5) .maxstack 4 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 IL_0003: div IL_0004: ret } // end of method Program::CalculateVelocity 

所以有些事情无法在F#中反映出来。 这是真的吗? 看到评论:CLR中的单位实际上根本没有被看到……在文章中。

正如其他人已经指出的那样,当您需要获取有关已编译F#类型的一些信息时,您可以使用标准的.NETreflection( System.Reflection )和F#reflection,它提供有关受歧视的联合,记录等的信息。( Microsoft.FSharp.Reflection )。

遗憾的是,无法使用这两个API中的任何一个访问有关度量单位的信息,因为它们仅在编译期间进行检查,并且在运行时实际上不存在(它们无法以任何方式在CLR中表示)。 这意味着您永远无法确定例如盒装浮点值是否具有某种度量单位…

您可以使用F#PowerPack中的Metadata命名空间获取有关度量单位的一些信息。 例如,以下打印foo是一个单位:

 namespace App open System.Reflection open Microsoft.FSharp.Metadata [] type foo module Main = let asm = FSharpAssembly.FromAssembly(Assembly.GetExecutingAssembly()) for ent in asm.Entities do if ent.IsMeasure then printfn "%s is measure" ent.DisplayName 

这将读取编译器存储在编译文件中的一些二进制元数据(以便在引用其他F#库时可以看到单元),因此您应该能够看到有关F#库的公共API的信息。

度量单位只是编译时的事情,它在程序集/ CLR中不存在。

从第一部分 :

度量单位不仅仅是方便的常量注释:它们存在于值的类型中,而且,F#编译器知道单位的规则。

您可以:

.NET和F#reflection

F#库还扩展了.NET System.Reflection以提供有关F#数据类型的其他信息

资源