C#/CLI标识符的最大长度是多少?

31
除了在特定范围内必须唯一之外,还有哪些关于名称的限制?这些限制在哪里定义?
6个回答

56

除了其他答案之外,微软Visual C#编译器接受的最大标识符长度为511个字符。 可以使用以下代码进行测试:

class Program
{
    private static void Main(string[] args)
    {
        int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 5;
    }
}

变量名长度为511个字符。此代码可以编译,但如果名称添加一个字符,则编译器将输出error CS0645:标识符太长


12
现在似乎不再是这种情况,至少在Visual Studio 2015编译器中是这样。我尝试了一个16,000字符的标识符,只是得到一个警告说这个名称对于PDB来说太长了,所以调试会受到影响,但它应该可以正常运行。 - Kurt Hutchinson
现在即使使用VS 2019也没有任何警告。 - Iftikhar Ali Ansari

26

来自ECMA-335的PDF,第二部分,第22节:

元数据保留名称字符串,如编译器或代码生成器创建的那样,不做任何更改。基本上,它将每个字符串视为不透明的块。特别是,它保留大小写。CLI对存储在元数据中并由CLI后续处理的名称长度没有限制。

如果我正确理解并且上下文正确,则CLR中标识符的长度实际上没有限制。


.NET的C#编译器会保留实际源文件中的名称吗?这是否意味着使用较长的变量名会使程序效率降低? - fearofawhackplanet
4
@fearofawhackplanet:磁盘利用率较低。但元数据在正常程序执行期间不会被使用,因此它并不会真正影响运行时性能。 - Ben Voigt
2
@BenVoigt 是的,除非您使用反射。 - bcl

16
C#语言规范在统一C# 3.0规范的第2.4.2节中定义了标识符。基本上是以“字母或下划线”开头,后面跟任意数量的“字母、十进制数字、连接字符、组合字符、格式字符”。如果要将关键字用作标识符,则需要在前面加上@符号,例如int @int = 5;
我没有研究CLI规范,但我知道它比C#规范略微宽松,因为C#编译器使用难以理解的名称表示匿名方法之类的东西-这些通常包括尖括号,这在CLI中有效但不在C#中有效。
编辑:C#规范中没有显式的名称长度限制,但第2.4.2节有一个保留:
“包含两个连续下划线字符(U+005F)的标识符由实现专用。例如,实现可能提供以两个下划线开头的扩展关键字。”
换句话说,特定以__开头的标识符是否有效取决于具体实现(某些编译器可能将__foo作为扩展关键字,而有些则可能不会)。

1
@Jasmine:是的 - 并不是说它明确被禁止了,而是编译器可能想要将其用于其他用途,因此您可能会发现在某些实现下它会出错。 - Jon Skeet
public static List<int> __95E7AE42_2026_4B2D_A0CE_3DE477AADF28; //也可以 - Jasmine
我只是想让你知道我为什么用负评烧掉了声望。 - Jasmine
1
@Jasmine:你因为我引用规范而给我点下了反对票?(那就是规范所说的...) - Jon Skeet
是的,因为规范的那部分内容具有误导性。 - Jasmine
1
@Jasmine:不是特别的。我会给出更完整的引用和更多细节。 - Jon Skeet

12
根据《Expert .NET 2.0 IL Assembler》(Serge Lidin,Apress)中的各个部分,功能CIL/CLR限制为UTF-8编码中的1,023个字节。引用如下:
第122页:
ILAsm中任何一种名称的长度在语法上没有限制,但元数据规则对名称长度施加了某些限制。
第126页:
公共语言运行时对完整类名长度施加限制,指定其在UTF-8编码中不应超过1,023个字节。然而,ILAsm编译器不强制执行此限制。如果在ILAsm中为简单名称使用单引号,则它们是纯词汇工具,不会出现在元数据中;因此,它们不会对完整类名的总长度产生影响。
第143页:
[TypeDef表]名称和命名空间条目引用的字符串的组合长度不能超过1,023个字节。
第144页:
[TypeRef表][run time]名称和命名空间条目引用的字符串的组合长度不能超过1,023个字节。
第186页:
[Method表]名称(#Strings流中的偏移量)。方法的名称(不包括该方法所属类的名称)。此条目必须索引长度不超过1,023个字节的非零长度的字符串。

3
这可能是为什么在C#编译器中,511字符标识符会产生错误的原因,因为每个字符都是双字节,所以会有1022个字节,而我猜测还有几个字节的开销超过了1023字节的限制。 - AaronLS
2
如果它们在UTF-8中不能超过1023个字节,那么每个字符都不是双字节值,而通常是1个字节(大多数情况下使用US-ASCII),每个符号最多可达六个字节。当然,您可以使用各种组合符号来表示“字符”,因此这相当复杂。但是,在UTF-8中,511个字符并不总是加起来等于1022个字节。 - Sami Kuhmonen

1

Visual Studio 2015 (更新3) - C# 6

类名最大长度 = 993 个字符

    public class AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAAAZZZ
{            
}

如果你再添加1个字符,它就无法编译,而且错误列表也是空的!
编辑:对于使用VS2013 Update 3的同事,类名限制为1012。不知道原因为何。

3
据我所知,你回答中的类名有992个字符,而不是993个(记住,大多数编辑器在显示行和列位置时使用基于1的计数)。然而,你获得这个答案的原因可能是因为你把这个类放到了一个名称为30个字符的命名空间中。命名空间是类名的一部分,.分隔符也要计算在内,因此将31个字符添加到992个字符中,你就可以得到正确且预期的结果,即1023个字符。 - Glenn Slayden

0

在分区II元数据文档中,它指出标识符可以是ID或SQSTRING

ID被描述为

一个由连续字符组成的字符串, 它以字母字符或“_ ”、“$”、“@”或“?”之一开头, 然后是任意数量的字母数字字符或“_ ”、“$”、“@”或“?”之一。

这意味着没有长度限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接