.net 如何确定编译器是否命名了union case属性
F#允许您选择命名联合案例属性。 如果没有,编译器将在编译期间自动为您选择一个名称(Item1…n) 我唯一能想到的就是对返回的名称进行简单的字符串比较.net 如何确定编译器是否命名了union case属性,.net,f#,.net,F#,F#允许您选择命名联合案例属性。 如果没有,编译器将在编译期间自动为您选择一个名称(Item1…n) 我唯一能想到的就是对返回的名称进行简单的字符串比较 让testCase=命名为“bar” 让caseInfo,=FSharpValue.GetUnionFields(testCase,typeof) caseInfo.GetFields() 有没有更可靠的方法来确定名称是否由编译器生成?这是一个非常有趣的问题。事实证明,case字段实际上并不是存储为System.Tuple,而是编译成标准的.
让testCase=命名为“bar”
让caseInfo,=FSharpValue.GetUnionFields(testCase,typeof)
caseInfo.GetFields()
有没有更可靠的方法来确定名称是否由编译器生成?这是一个非常有趣的问题。事实证明,case字段实际上并不是存储为
System.Tuple
,而是编译成标准的.NET属性,在表示联合case的嵌套类上有一个支持字段
如果您在ILSpy或类似的反汇编程序中查看生成的代码,您会发现一些奇怪的片段:
\u nameOfProperty
)前面生成带下划线的支持字段(而不是属性)。因此,如果在union case嵌套类上调用GetMembers
,并提供NonPublic | | | Instance
绑定标志,则可以使用反射深入到它GetConstructors
,然后GetParameters
,来获得相同的信息Item42
-它将在编译时不带下划线,就像它是由编译器指定的一样。幸运的是,编译器足够聪明,可以跳过您已经使用过的序号因此,从理论上讲,您可以检测名称是否由用户提供,但这是一个繁琐、环境性的问题,而且取决于内部实现细节,而这些细节并不能保证保持原样。我很惊讶这些名称在编译过程中没有被删除
Item1..n
只是标准的System.Tuple
元素名称。这是我没有想到的一种可能性,但我很高兴这些名称仍然存在。但是是的,Item1..n是标准系统。元组名称。如果您只有一个未命名的属性,它将该属性命名为“Item”。我的.net IL-foo不够强大,但我用LinqPad做了一个快速的示例:我希望其他人会得出不同的结论。我也注意到了背景字段中的下划线。但这似乎没有提供比检查属性名称更确定的信息。所以我想我要用我已经有的东西。因为只有我会使用这些代码,所以我应该很好。另一方面,如果我读对了,如果目标是.net<4,它会编译成一个System.Tuple。@Brunner:该文档描述的是在.net 4.0之前,BCL中没有System.Tuple
,而F#使用了FSharp.Core
中存在的该类型的本地副本。这与DUs的编译方式无关。welp,你是对的,应该重新阅读主题的标题。
type Foo =
| Nothing
| AutomaticallyNamed of string
| Named of nameOfProperty: string
let testCase = Named "bar"
let caseInfo, _ = FSharpValue.GetUnionFields(testCase, typeof<Foo>)
caseInfo.GetFields()