是否可以在C#中创建System.Int32?

时间:2012-10-26 06:36:25

标签: c# clr

如果你深入了解,C#中的值类型将由编译器/ CLR特别处理。但是CLR内部的类型更加特殊。这就是我的意思:

int a = 5;
int b = 10;
int с = a + b;
a.CompareTo(b);

您可以将鼠标悬停在Visual Studio中的int上,看看它实际上是System.Int32 struct。没关系。现在你可以获取ILDasm并查看System.Int32是什么:转换它是一个非常简单的struct,其中一个类型为int32的字段(这是CLR内部的int32)并且没有重载运算符。

那么,int с = a + b如何运作呢?我再次抓住ILDasm并研究IL。事实证明IL代码中没有System.Int32:编译器自动理解它应该用int32替换它。 IL指令add适用于堆栈上的int32个。更让我感到有趣的是,CLR允许在System.Int32上调用int32的实例方法。看起来像是一些黑魔法。

所以,这里是纯粹的理论问题:似乎System.Int32的类型与其他类似,是否可以用C#创建?如果可以的话,你能用它做一些有用的事情(实际的int32字段是私有的吗?)

修改:好了,为了更清楚一点:这个问题与int System.Int32的别名无关。可以采用提供的示例,将int替换为System.Int32,并在示例后跳过第一段。真正的问题是有可能在您的IL代码中使用valuetype [mscorlib]System.Int32 a而不仅仅是int32 a

3 个答案:

答案 0 :(得分:2)

因此,请考虑以下代码:

    static void Main(string[] args)
    {
        int x = 5;
        Print(x);
        Console.ReadLine();
    }

    static void Print(object x)
    {
        int y = (int)x;
        Console.WriteLine(y);
    }
ILDasm中的

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  .maxstack  1
  .locals init ([0] int32 x)
  IL_0000:  nop
  IL_0001:  ldc.i4.5
  IL_0002:  stloc.0
  IL_0003:  ldloc.0
  IL_0004:  box        [mscorlib]System.Int32
  IL_0009:  call       void Test.Program::Print(object)
  IL_000e:  nop
  IL_000f:  call       string [mscorlib]System.Console::ReadLine()
  IL_0014:  pop
  IL_0015:  ret
} // end of method Program::Main

.method private hidebysig static void  Print(object x) cil managed
{
  .maxstack  1
  .locals init ([0] int32 y)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  unbox.any  [mscorlib]System.Int32
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_000e:  nop
  IL_000f:  ret
} // end of method Program::Print

[mscorlib]System.Int32仅用于装箱/取消装箱。当变量在堆栈中时,它总是int32


来自Int32 and int

将System.Int32视为int32的阴影类型可能会有所帮助。

以下C#代码:

int x = 0;
x.ToString();

这是IL:

ldc.i4.0
stloc.0
ldloca.s 0
call instance class System.String [mscorlib]System.Int32::ToString()
pop

注意它是如何将int32传递给看似不兼容的System.Int32 结构。引擎允许这个因为它已被硬连线识别 System.Int32作为int32的影子类型。

答案 1 :(得分:1)

int32 vs int(== System.Int32

来自Understanding .NET Primitive Types

  

int32是一个CLR原语。然后在FCL中,它表示为   System.Int32结构。 System.Int32的整数值保持不变   它的m_value已归档,并且定义了许多与整数相关的方法   System.Int32。

     

在C#中,int只是System.Int32的别名,由C#支持   编译器。因此int和System.Int32

之间没有依赖关系

来自IL "The Language of CLR"

  

.NET下的所有编译器都会生成中间语言   用什么语言来开发应用程序。事实上,CLR不会   了解用于开发应用程序的语言。所有语言   编译器将生成一种统一的通用语言Intermediate   语言。

因此,在C#System.Int32中我们对IL int32有所了解。我不知道直接使用C#代码处理IL的方法,实际上看不出任何理由。

有一个:Tool to allow inline IL in C# / VB.Net


至于int vs System.Int32

关于SO的帖子和SO上的System.Int32:C#, int or Int32? Should I care?

在MSDN中:

  1. Int32 Structure
  2. int (C# Reference)
  3. 一切都是一样的:

    Int32 i = new Int32();
    Int32 j = 5;
    int x1 = 2;
    Int32 x2 = x1;
    

    int可以说语法糖 ......实际上它是System.Int32

    除了看看C#语言规范4.1.4简单类型:

      

    C#提供了一组称为简单类型的预定义结构类型。   简单类型通过保留字识别,但这些   保留字只是预定义结构类型的别名   系统名称空间,如表

    中所述

    ,其中

    1. short => System.Int16
    2. int => System.Int32
    3. long => System.Int64
    4. 等等。

答案 2 :(得分:0)

CLR有一组原始类型,它们由CorElementType枚举定义。 http://msdn.microsoft.com/en-us/library/ms232600.aspx

add,sub,div,rem等操作码对这些类型进行操作。 JIT会将这些变成一些快速汇编代码。你无法定义新的。如果您有兴趣,可以查看它使用SOS生成的代码。

如果要模拟语言​​体验,可以在类型中使用运算符重载。 http://msdn.microsoft.com/en-us/library/8edha89s.aspx