对F#度量单位的反思

时间:2010-10-23 18:32:16

标签: c# reflection f#

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

// Learn more about F# at http://fsharp.net

[<Measure>] type m
[<Measure>] type cm

let CalculateVelocity(length:float<m> ,time:float<cm>) =
    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中的单位实际上根本没有被看到......在文章中。

3 个答案:

答案 0 :(得分:18)

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

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

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

namespace App
open System.Reflection
open Microsoft.FSharp.Metadata

[<Measure>] 
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的信息。

答案 1 :(得分:3)

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

来自part one

  

衡量单位不仅方便   关于常数的评论:它们在那里   在价值的类型,什么是   更多,F#编译器知道规则   单位。

答案 2 :(得分:1)

你可以:

  

.NET和F#Reflection

     

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

Source