标签:
杂谈 |
分类: C#编程 |
1. C#中的System.Int32和int
MSDN说,int只不过是System.Int32的马甲(别名)而已。在Visual Studio 2008里折腾的时候,突然看见System.In32 的定义里居然多处使用了int这个关键字:
http://www.cnblogs.com/images/cnblogs_com/yandixin/Int32.gif感觉有点别扭。于是用Reflector反汇编了mscorlib.dll(见注1),发现Int32的定义里确实使用了很多int:
http://www.cnblogs.com/images/cnblogs_com/yandixin/In32_reflector.gifSystem.Int32作为一个struct,在方法中使用自己问题不大,比如int CompareTo(int value);但是在字段中使用自己应该是不行的,比如int m_Value。
可以自己实验一下:
{
}
以上代码可以通过编译,但是下面的不行:
{
}
编译时会报错:Struct member 'Test.value' of type 'Test' causes a cycle in the struct layout。
所以这就让人感觉,Int32必须依赖于int才能实现:
- 似乎是先有int,再用int来实现了System.Int32,否则System.Int32的源代码将无法编译,网上有朋友把这比喻成“先有鸡还是先有蛋”的问题;
- 这样一来,int和System.Int32就不是MSDN上说的马甲的关系了。
难道int是一个比Int32更基本的东西?或者,Int32是如何自己把自己定义出来的?
2. IL中的System.Int32和int32
我们看一下mscorlib.dll中,System.Int32的IL:
http://www.cnblogs.com/images/cnblogs_com/yandixin/Int32_il_1.gif......
http://www.cnblogs.com/images/cnblogs_com/yandixin/Int32_il_2.gif可以看出,C#中的struct名称System.Int32对应为IL的System.Int32,而代码中的int关键字对应为IL中的int32。这让人感觉:C#的System.Int32对应IL的System.Int32;C#的int对应IL的int32。
我们再自己写一段代码来实验一下:
{
}
{
}
上面两个方法对应的IL一模一样:
http://www.cnblogs.com/images/cnblogs_com/yandixin/Int32_il_test.gif这时C#的System.Int32
上面是C#中System.Int32和int的实例的IL,下面看看方法调用:
{
}
{
}
两个方法的IL也一模一样:
http://www.cnblogs.com/images/cnblogs_com/yandixin/Int32_il_test2.gif而这时,C#的System.Int32 / int上的方法调用都对应到IL的System.Int32上去了。
究竟怎么回事?根据装配脑袋兄的解释,应该是这样的:
- IL中的int32是基元类型(primary type),IL中的System.Int32是对前者的封装;
- C#中的System.Int32和int语义上是等价的,马甲而已;
- C#中用System.Int32 / int定义的值对应到IL中的int32基元类型;
- C#中的System.Int32 / int用于任何其他需要.NET类型的语义时(比如要调用其上的方法时),则对应到IL中的System.Int32。
3. 称呼:Int32还是int
《Framework Design Guidelines》一书中说:我们要避免在标志符中使用语言特有的名字(别名)来称呼它们。因为别名没有增加任何价值,反而引起了大量的混淆。
《CLR via C#》的作者Jeffrey Richter还举了个例子:VB可以抛出 NullreferenceException这个异常,但是VB并不使用null,而是使用Nothing。
这样我们就可以理解,我们常用的Convert.ToInt32()为什么不叫ToInt(),Convert.ToInt64()为什么不叫ToLong()。
这一原则的一个重要目的,是充分利用.NET跨语言协作的特性。所以我们平常仅用C#进行开发时,使用int这种词汇并不会有什么明显的副作用,但是,理解“避免使用语言特有的名字”这一原则仍然是重要的。
4. 参考
- Framework Design Guidelines
- C# 语言参考:内置类型表
- .NET
Framework 3.5 Architecture
- Silent Void:Boolean和bool VS 鸡蛋和鸡
- SZW: 为《理解C#中的System.In32和int:并非鸡和鸡蛋 》做个续
- Anders Liu:也说System.Int32和int
注:
- .NET 3.5并不是完全独立于.NET 2.0和.NET 3.0 的,.NET 3.5并不提供独立的3.5版的mscorlib.dll,而是更新了.NET 2.0的mscorlib.dll,并使用该dll。所以大家在 WINDOWS\Microsoft.NET\Framework\v3.5\下会找不到mscorlib.dll这个文件。我这里反汇编的正是Framework\v2.0.50727\下的 mscorlib.dll。
- 顺便说一下,下面的两个方法:
publicint TestInt() int
{
test =0;
test; public
}Int32 =TestInt32()
{
Int32 test new Int32(); return
test;
}
对应的IL也是一样的:
http://www.cnblogs.com/images/cnblogs_com/yandixin/Int32_il_test3.gif
再次感谢大家的讨论!尤其是指出我的错误的几个朋友!
就好像我当初很诧异string和String为什么要弄两个,只是大小写不一样。
于是开始了一段比较简单的测试。
光从表面上看,它们输入时候的颜色是不一样的。string和int,你在vs默认样式下输入是蓝色的,而String和Int32你输入是偏淡绿色的。这个只是表面上的不同,但我以次确定它们绝对不可能是一模一样的(即使作用似乎一样),都是下同样蛋的鸡,却是两只不同实体的鸡(或者说也可能同样是一只鸡下出来的蛋,却是分两窝的。亦或一个却是另一个经过漂染的“马甲”。但肯定不是双黄蛋)。
于是我反查了代码颜色(大家也可以到工具>选项里面对照),并且特意改变样式进行辨别确认,结果如下:
string和int对应的是Keyword
String和Int32对应的都是User Types