在非ASCII语言中编码

5

嗯,我觉得这很奇怪,但在C#中,你实际上可以用不同的语言编写源代码。我已经用韩语写了一个示例源代码来说明我的观点:

namespace 대한민국 {
    public class 학생 {
        public string 이름 { get; private set; }
        public string 좌우명 { get; private set; }

        public 학생(string 이름, string 좌우명) {
            this.이름 = 이름;
            this.좌우명 = 좌우명;
        }
    }
    public class 대학교 {
        private List<학생> 재학생목록 = new List<학생>();

        public void 입학(학생 입학생) {
            재학생목록.Add(입학생);
        }

        public void 재학생출력() {
            foreach (학생 선택된학생 in 재학생목록) {
                Console.WriteLine("이름: {0}", 선택된학생.이름);
                Console.WriteLine("좌우명: {0}", 선택된학생.좌우명);
            }
        }
    }
    public class 프로그램 {
        static void Main(string[] args) {
            대학교 스쿨오브헬 = new 대학교();
            스쿨오브헬.입학(new 학생("전땅끄", "본인은 단돈 29만원과 땅끄로 이 신성하고 거룩한 국가의 민주주의를 발전시켰소"));
            스쿨오브헬.입학(new 학생("이피카츄", "여러분 이거 다 거짓말인거 아시죠!!!"));
            스쿨오브헬.입학(new 학생("빵상아줌마", "빵빵 똥똥똥똥 땅땅 따라라라라~~~"));

            스쿨오브헬.재학생출력();
        }
    }
}

以上代码编译后会输出有效结果。

除了关键字外,您实际上可以使用其他语言编写源代码,而不是英语。当然,这是非常不切实际的,没有人会这样做。

我的问题如下:

  • 这是C#功能还是Visual Studio功能?(我无法在Visual Studio 2010下的C++中获得类似的程序)
  • 性能影响如何?(我很容易地假设几乎没有,但不确定是否进行了任何疯狂的转换以允许非ASCII字符进行编码)
  • 实现此功能的原因是什么?

2
如果(指项目中的所有开发人员)那些语言,那么这并不是不切实际的。我看过使用非英语编写类名和成员名称的代码。这一点也不成问题。 - Marc Gravell
1
@MarcGravell 奇怪的是,作为一名英语非母语者,我倾向于不喜欢代码中出现非英语的情况。(英语在编程方面有一些实际优势,其中最重要的是几乎没有名词变格。这使得语句形成的“句子”违反语法的情况比其他一些语言少得多。) - millimoose
2
@MarcGravell 并不完全正确。因为关键字(以及可用的库方法等)都是英语,使用非英语的类名和成员名称会真正“破坏”代码的阅读流畅性,即使你能理解所使用的语言。 - Bart Friederichs
2
@Oded 是的,但是显然 SO 上的每个帖子都会将其问题简化为一个最小化的示例,该示例仅显示解决问题所必需的概念,因此可以在那时进行重命名(咯咯笑)。 - Marc Gravell
2
@BugFinder 喜欢 for(int ı = 0; ı < 10; ı++) {...} 吗? - Marc Gravell
显示剩余13条评论
2个回答

5

1:这在C#语言规范中有说明,因此:C#

2:完全没有;解析器并不关心某些东西是Fred还是프로그램;对编译器来说,两者都没有意义

3:因为并非所有的开发人员以英语(或拉丁语系)为母语。对于那些正在开发该项目的开发人员来说,프로그램很可能可以轻松明确地表达类的意图并具有意义。


对于第三点,我更倾向于说这不是“实现一个功能”,而是“不移除一个功能”。C#本地字符集是Unicode而不是ASCII,因此没有理由像基于ASCII的语言那样区别对待ASCII 127以上的字符。 - Gorpik

3

1) C#规范和CLI规范都允许这样做。

C#标准规定:

源文件是一个有序的Unicode字符序列。

并且:

符合规范的程序中,标识符必须采用由Unicode标准附录15定义的规范格式C的格式。遇到不符合C规范化的标识符的行为是由具体实现决定的,但不需要进行诊断。

ECMA CLI规范如下所述:

I.8.5 命名

命名是给类型系统的实体赋予名称,以便其他类型系统的部分或类型的实现可以引用它们。类型、字段、方法、属性和事件都有名称。就类型系统而言,值、局部变量和参数没有名称。类型系统的实体被赋予单个名称(例如,一个类型只有一个名称)。

I.8.5.1 有效名称

所有名称比较都是按字节比较(即区分大小写,与语言环境无关,也称代码点比较)进行的。在名称用于访问内置VES提供的功能(例如,类初始化方法)时,始终会在定义上附带指示,以避免构建任何一组保留名称。

下面是重要的内容:

CLS规则4:程序集应遵循Unicode标准3.0技术报告15的附录7,该报告规定了允许在标识符中启动和包含的字符集。该报告可在http://www.unicode.org/unicode/reports/tr15/tr15-18.html上在线获取。标识符应采用Unicode规范化形式C的规范格式。为了满足CLS要求,如果两个标识符的小写映射(由Unicode区域设置不敏感的一对一小写映射指定)相同,则它们相同。也就是说,为了使两个标识符在CLS下被视为不同,它们必须有更多不同之处,而不仅仅是大小写。但是,为了覆盖继承定义,CLI要求使用原始声明的精确编码。

[注:CLS(消费者):无需消耗违反CLS规则4的类型,但必须具有允许访问使用自己关键字作为名称的命名项的机制。CLS(扩展器):无需创建违反CLS规则4的类型。应提供一种机制来定义遵守这些规则但与语言中的关键字相同的新名称。CLS(框架):不应导出违反CLS规则4的类型。应避免在编程语言中常用作关键字的名称。

2) 完全不应该有性能影响。CLI规则规定,必须使用Unicode区域设置不敏感映射来匹配名称,这意味着当需要比较两个名称时,必须将其转换为Unicode代码点序列。如果编译器或运行时选择在可变长度编码(如UTF-8)中保留此信息,并在运行时转换为代码点,则从理论上讲可能会有一些性能差异;但实际上,我不认为会有任何实现这样做,或者如果它们这样做了,性能差异是可以测量的。

请注意,CLS规则4指出,“为了覆盖继承定义,CLI要求使用原始声明的精确编码”,这确实对覆盖名称时施加了特定限制。但由于这不是普遍要求,因此“在比较之前将所有内容转换为代码点”仍然必须实现。

3) 再次强调,这是CLI规范,因此语言必须执行。


你对第三点的解释有些循环论证。CLI规范、C#规范和C#编译器都受到微软和少数合作伙伴的控制,所以它们不像C++那样与特定的实现供应商紧密相关。(我想象) - millimoose
@millimoose:CLI规范由ECMA控制。此外,除了C#之外,还有其他针对CLI的语言,例如boo;这个论点适用于所有这些语言。 - Jon
CLI规范已提交给ECMA进行标准化,它并不是由ECMA的工作组开发的。仅从时间上来看,后者是不可能的——维基百科称该提交是在2000年中期发生的,而当时.NET已接近测试版状态,CLI肯定已经在研发多年了。就所有实际目的而言,微软是指定CLI的一方,并且可以自由决定允许在标识符中使用什么。我还会认为,在这种情况下,C#和CLI之间的区别是人为的,因为两者是同时创建的。 - millimoose

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