加载中…
个人资料
李云
李云
  • 博客等级:
  • 博客积分:0
  • 博客访问:690
  • 关注人气:13
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

理解C#中的System.Int32和int

(2008-01-21 20:42:02)
标签:

杂谈

分类: C#编程
<转自CSDN>

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.gif

System.Int32作为一个struct,在方法中使用自己问题不大,比如int CompareTo(int value);但是在字段中使用自己应该是不行的,比如int m_Value。

可以自己实验一下:

public struct Test
{
    
public Test GetTestInstance(Test test)
    {
        
return test;
    }
}

以上代码可以通过编译,但是下面的不行:

public struct Test
{
    
//like int m_value in System.Int32
    public Test 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。

我们再自己写一段代码来实验一下:

public int TestInt(int value)
{
    
int test = value;
    
return test;
}
public Int32 TestInt32(Int32 value)
{
    Int32 test 
= value;
    
return test;
}

上面两个方法对应的IL一模一样:

http://www.cnblogs.com/images/cnblogs_com/yandixin/Int32_il_test.gif

这时C#的System.Int32 / int都对应IL的int32。

上面是C#中System.Int32和int的实例的IL,下面看看方法调用:

public int TestInt(int value)
{
    
int test = int.Parse(value.ToString());
    
return test;
}
public Int32 TestInt32(Int32 value)
{
    Int32 test 
= Int32.Parse(value.ToString());
    
return test;
}

两个方法的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. 参考

注:

  • .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。
  • 顺便说一下,下面的两个方法:
    public int TestInt()
    {
        
    int test = 0;
        
    return 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

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有