c#中关于String、string,Object、object,Int32、int
在java中,string和String有着明显的区别,后者就是前者的一个封装。在c#中,好像是通用的,大部分情况下,两者互换并不会产生问题。今天特意查了一下资料,了解了一下两者的关系。
简单的讲,String指的是System.String类别,而string则是C#内建的关键字。事实上,string正是对应到System.String类别,也可说string是System.String 类别在C#中的化名(alias),因此对两者的应用会生成相同的IL码,对於CLR而言这两者是没什么差别的。
再具体一些,就要从内建类型(Predefined Type)谈起了。 内建类型,又称做原生类型(Primitive Type),顾名思义就是一个语言内建的类型。也就是说,一个符合该语言标准的编译器,应该要能直接支援这种类型。一般来讲,这意味著该语言应该会为该类型规范出一个语言关键字,而编译器要能认得这个关键字并在编译时产生适当代码。以C#来说,像是整数(int),浮点数(float),字符串(string)等都是内建类型,我们可以直接使用这些关键字,而C#编译器将能看懂这些关键字并编译出适当的IL码供执行之用。通过这样的方式会方便我们进行编码。比如要用一个变数来储存年龄时,是
int age = 20;
还是
System.Int32 age = new System.Int32();
age = 20;
毕竟整数,浮点数,字元,字串等在程序中实在太常用了。如果每次都来一行
System.Int32 age = new System.Int32();
实在麻烦。此外,内建类型也意味著编译器在设计时就已经了解这些类型的实作细节,所以编译器对于内建类型可以有更多的识别方法,因而能更有弹性且有力的处理这些类型。举例来说,在使用内建类型时我们可以不用new来new去,一行
int i = 10;
就通通搞定。而在将精度较低的内建类型转型至精度较高的内建类型时我们可以不需多做指示地让它隐式转型(Implicit cast):
int i = 20;
double j = i;
当然,这和派生类别能自动向上转型(upcast)为基类别的情况并不一样,因为int并不是继承double而来,他们都是继承自System.ValueType,换言之,在继承体系之中,他们俩是平行的。此例之中int之所以能自动地转型成double乃是因为编译器知道int和double这两个内建类型是做什么用的,并判断出可以无害的将int转型为double,因此能顺利编译过关且正常运作。
那么,到底要String还是string呢 现在,我们应该已经知道什么叫内建类型,也了解到String和string到最後都是一样的,因为这两种程式码都会产生相同的IL码。那么,我们到底应该使用哪种风格来写程式呢 在C#语言规格书1.2.1中是这样说的:「As a matter of style, use of the keyword is favored over use of the complete system type name.」很明显地它的建议是使用关键字。不过相反的主张也有人支持,基本精神是认为使用FCL名称会使程式较为清楚,因为同一个FCL类型在不同语言也许会使用不同的别名(alias),或是相同的别名在不同的程式语言中可能会对应到不同的FCL类型,使用FCL名称可以避免必须使用多种语言工作或不熟悉此语言的程式设计师产生混淆。举例来说,如果程式中是清清楚楚的宣告成Int32,那无庸置疑地这个变数就是Int32。但若是宣告为long,那在某些语言可能是对应到Int32,有些则是对应到Int64。基本上,我个人是觉得两种风格间没有明显优劣差异,所以依喜好择一即可,唯一的建议是:最好不要混用。混用会导致程式风格混乱,在阅读和维护上都有可能造成困扰。