我在业余时间正在研究一个交互式编译器,我发现我可以使用 a 定义一个类型,TypeBuilder
它定义了两个具有相同名称的字段(并且该类型显然会发出并运行它的初始化程序,这些静态字段被初始化,只是美好的) 。查看我的监视窗口:
我觉得这很奇怪:具有两个同名字段的类型有什么实际用途?根据 CLR 规范,这真的是“合法的”(会对参考感兴趣),还是这种未定义或非法的行为TypeBuilder
可能是不允许的?
我在业余时间正在研究一个交互式编译器,我发现我可以使用 a 定义一个类型,TypeBuilder
它定义了两个具有相同名称的字段(并且该类型显然会发出并运行它的初始化程序,这些静态字段被初始化,只是美好的) 。查看我的监视窗口:
我觉得这很奇怪:具有两个同名字段的类型有什么实际用途?根据 CLR 规范,这真的是“合法的”(会对参考感兴趣),还是这种未定义或非法的行为TypeBuilder
可能是不允许的?
这在ECMA-335 CLI 规范的§I.8.5.2 中有解释:
通常,名称不是唯一的。名称被收集到称为范围的分组中 。在一个范围内,一个名称可以引用多个实体,只要它们属于不同类型(方法、字段、嵌套类型、属性和事件)或具有不同的签名。
CLS 规则 5:在符合 CLS 的范围内引入的所有名称都应独立于种类而不同,除非名称相同并通过重载解析。也就是说,虽然 CTS 允许单个类型对方法和字段使用相同的名称,但 CLS 不允许。
我理解这一点的方式,这意味着您可以在同一类型中拥有两个具有相同名称的不同字段,但它们必须具有不同的签名,即不同的类型。因此,如果您有两个字段string x
和int x
,那么根据 CLI 规范就可以了。根据公共语言规范 (CLS) 是不行的,但这基本上只是一组使语言互操作性更容易的规则。
另一方面,具有两个具有相同名称和类型的字段的类型是不合法的,如果您在具有类似类型的程序集上运行 PEVerify,它确实无法通过验证:
[MD]:错误:字段重复,令牌=0x04000002。[令牌:0x04000001]
[MD]:错误:字段有重复,令牌 = 0x04000001。[令牌:0x04000002]
出于某种原因,CLR 似乎没有进行此检查,因此它允许此类无效类型。C# 编译器也能够处理此类类型,它似乎选择了两个字段之一并使用它。