7

If you get under the hood, value types in C# are treated very specially by compiler/CLR. But types internal to CLR are treated even more specially. Here is what I mean:

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

You can hover with your mouse over int in Visual Studio and see that actually it is System.Int32 struct. That's OK. Now you can grab ILDasm and look into what System.Int32 is: turns over that it is very simple struct with one field of type int32 (this is int32 internal to CLR) and there is no overloaded operator for addition.

So, how this int с = a + b works then? Again I grab ILDasm and look into IL. Turns out that there is no System.Int32 in IL code: compiler automatically understands that it should replace it with int32. And there is IL instruction add that works for couple of int32 on a stack. What amuses me even more, CLR allows to call instance methods for System.Int32 on int32. Looks like some black magic to me.

So, here goes the pure theoretical question: seems that System.Int32 is type like any other, could it be created in C# somehow? And if it could, could you do anything useful with it (actual int32 field is private)?

Edit: Ok, to make it a bit more clear: this question have nothing about int being alias to System.Int32. One can take provided example, replace int with System.Int32 and skip first paragraph after the example. The real question is about possibility to have valuetype [mscorlib]System.Int32 a in your IL code instead of just int32 a.

iw.kuchin
  • 738
  • 6
  • 14
  • 1
    `int a = new int();` is the same as `System.Int32 a = new System.Int32();`. It's just syntactic sugar. Both will be represented internally as `int32`. Even though there are a handful of structs in the CLR that are handled "magically", it's better than some other languages like Java where getting all the extras requires boxing/unboxing. – Robert Rouhani Oct 26 '12 at 06:48

3 Answers3

2

So, consider the following code:

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

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

in 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 is used for boxing/unboxing only. When the variable is in stack, it's always int32.


From Int32 and int:

It might be helpful to think of System.Int32 as a shadow type for int32.

The following C# code:

int x = 0;
x.ToString();

Is this in IL:

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

Notice how it's passing an int32 into a seemingly incompatible System.Int32 struct. The engine allows this cause it has been hardwired to recognise System.Int32 as the shadow type of int32.

horgh
  • 17,918
  • 22
  • 68
  • 123
  • One can move further with boxing example: `int a = 5; int b = 10; Object oa = a; Object ob = b; Int32 с = ((Int32)oa) + ((Int32)ob);` If you examine IL you'll see: `IL_0013: ldloc.2 IL_0014: unbox.any [mscorlib]System.Int32 IL_0019: ldloc.3 IL_001a: unbox.any [mscorlib]System.Int32 IL_001f: add` So, as `add` works with CLR primitives one can conclude that there is no such thing as "unboxed System.Int32" and `System.Int32` is used only for creating type objects. – iw.kuchin Oct 26 '12 at 09:08
1

int32 vs int(==System.Int32)

From Understanding .NET Primitive Types :

int32 is a CLR primitive. Then in FCL, it is represented by System.Int32 struct. The integer value of System.Int32 is persisted on its m_value filed, and a lot of integer-related methods are defined on System.Int32.

In C#, int is just an alias for System.Int32, supported by the C# compiler. So there is no dependency between int and System.Int32

From IL "The Language of CLR":

All compilers under .NET will generate Intermediate Language no matter what language is used to develop an application. In fact, CLR will not be aware of the language used to develop an application. All language compilers will generate a uniform, common language called Intermediate Language.

So, in C# System.Int32 is what we have for IL int32. I don't know the way to work with IL straight from C# code, and actually don't see any reason for.

There is one: Tool to allow inline IL in C# / VB.Net


As for int vs System.Int32:

A post on int and System.Int32 on SO: C#, int or Int32? Should I care?

In MSDN:

  1. Int32 Structure
  2. int (C# Reference)

It's all the same:

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

int is a so to say syntactic sugar...actually it is System.Int32

Besides have a look at C# language specs 4.1.4 Simple types:

C# provides a set of predefined struct types called the simple types. The simple types are identified through reserved words, but these reserved words are simply aliases for predefined struct types in the System namespace, as described in the table

where

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

and so on.

Community
  • 1
  • 1
horgh
  • 17,918
  • 22
  • 68
  • 123
  • But `int32` and `Int32` are not the same. There is no such thing as `int32` in C#. – iw.kuchin Oct 26 '12 at 07:09
  • read this: http://weblogs.asp.net/dixin/archive/2007/12/20/understanding-net-primitive-types.aspx – horgh Oct 26 '12 at 07:16
  • Nice article. But it explicitly states that I wrote above: `Int32` and `int32` are not the same (also `int` != `int32`). I'm not arguing about `Int32` and `int` here. The question is about `Int32` and `int32`. – iw.kuchin Oct 26 '12 at 07:26
  • Did you read the article: "*int32 is a CLR primitive. Then in FCL, it is represented by System.Int32 struct.*" – horgh Oct 26 '12 at 07:33
  • Sorry, don't get your point. I do understand that `Int32` is some magical wrapper around `int32`. They are definitely not the same because `int32` is a primitive and `Int32` is full-fledged type defined in mscorlib. There is really a lot of magic going there (see [this](http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/6d183671-2f42-4803-ac08-334d19708bc1) for example). But I see no answer to my original question here: is it possible to create `Int32`. – iw.kuchin Oct 26 '12 at 07:53
  • @iw.kuchin You are at least asking incorrectly. I guess you should ask, whether it is possible to create `int32` not 'Int32'(==System.Int32). And as the answer - no, as in C# you can only use FCL types, while int32 is IL type. Probably there is a way to address IL straight, but I wouldn't even guess what you could need this for. – horgh Oct 26 '12 at 08:06
  • @iw.kuchin http://www.c-sharpcorner.com/UploadFile/nrsurapaneni/ILtheLangOfCLRbyNRS12222005040956AM/ILtheLangOfCLRbyNRS.aspx – horgh Oct 26 '12 at 08:11
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18620/discussion-between-iw-kuchin-and-konstantin-vasilcov) – iw.kuchin Oct 26 '12 at 08:17
  • And, you can declare your aliases for any type via using keyword. using MyInteger = System.Int32; – Cihan Yakar Oct 26 '12 at 08:49
0

The CLR has a set of primitive types they are defined by the CorElementType enum. http://msdn.microsoft.com/en-us/library/ms232600.aspx

The add, sub, div, rem, etc opcodes operate on these types. The JIT will turn these into some fast assembly code. You cannot define new ones. You can look at the code it generates using SOS if you are interested.

If you want to emulate the language experience you can use operator overloads in your type. http://msdn.microsoft.com/en-us/library/8edha89s.aspx

AbdElRaheim
  • 1,384
  • 6
  • 8