gpt4 book ai didi

.net - 如何确定联合案例属性是否由编译器命名

转载 作者:行者123 更新时间:2023-12-01 13:41:47 25 4
gpt4 key购买 nike

F# 允许您有选择地命名联合案例属性。如果您不这样做,编译器将在编译期间自动为您选择一个名称 (Item1...n)。

type Foo =
| Nothing
| AutomaticallyNamed of string
| Named of nameOfProperty: string

我唯一能想出的就是对任何 GetFields 上的名称进行简单的字符串比较返回。

let testCase = Named "bar"
let caseInfo, _ = FSharpValue.GetUnionFields(testCase, typeof<Foo>)

caseInfo.GetFields()

是否有更可靠的方法来确定名称是否由编译器生成?

最佳答案

很有趣的问题。事实证明,case 字段实际上并未存储为 System.Tuple,而是被编译为标准 .NET 属性,并在表示联合 case 的嵌套类上使用支持字段。

如果您查看 ILSpy 或类似反汇编程序中生成的代码,您会发现一些奇怪的点点滴滴:

  1. 属性上没有任何内容可以告诉您它有一个用户提供的名称,因此如果您要在这里寻找一个漂亮干净的解决方案,那您就不走运了。

    <
  2. 但是,当字段具有用户提供的名称时,生成的支持字段(不是属性)将在名称前加上下划线(即 _nameOfProperty)。因此,如果您在联合案例嵌套类上调用 GetMembers 并提供 NonPublic |||,则可以使用反射向下钻取它实例绑定(bind)标志。

  3. 或者,联合案例类的单个非公共(public)构造函数的构造函数参数使用相同的名称,因此您可以通过检查构造函数的参数获取相同的信息 - GetConstructors 再次使用非公共(public)绑定(bind)标志,然后是 GetParameters

  4. 但事情从来没有这么简单 - 这里有一个警告,如果你实际上使用编译器使用的命名方案命名你的字段 - 即 Item42 - 它会在没有下划线的情况下编译,就好像它是由编译器分配的一样。不过幸运的是,编译器足够聪明,可以跳过您已经使用过的序数。

因此理论上您可以检测该名称是否由用户提供,但它很麻烦,而且取决于内部实现细节,不能保证保持原样。

关于.net - 如何确定联合案例属性是否由编译器命名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39497450/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com