2012-10-26 12 views
7

Jeśli pojawi się pod maską, typy wartości w języku C# są traktowane bardzo dokładnie przez kompilator/CLR. Ale typy wewnętrzne dla CLR są traktowane jeszcze bardziej. Oto co mam na myśli:Czy jest możliwe utworzenie System.Int32 w języku C#?

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

Można najechaniu myszką nad int w Visual Studio i zobaczyć, że faktycznie jest to System.Int32 struct. W porządku. Teraz możesz chwycić ILDasm i sprawdzić, co to jest System.Int32: przewraca, że ​​jest to bardzo prosta struktura z jednym polem typu int32 (jest to int32 wewnętrzny dla CLR) i nie ma przeciążonego operatora dla dodania.

Więc, jak działa int с = a + b? Ponownie chwytam ILDasm i patrzę na IL. Okazuje się, że w kodzie IL nie ma kodu System.Int32: kompilator automatycznie rozumie, że powinien go zastąpić numerem int32. I jest instrukcja IL add, która działa dla pary int32 na stosie. Co mnie bawi, CLR pozwala wywoływać metody instancji dla System.Int32 na int32. Wygląda mi na czarną magię.

Oto proste pytania teoretyczne: wydaje się, że System.Int32 jest typem podobnym do jakiegokolwiek innego, czy można go w jakiś sposób utworzyć w języku C#? A jeśli to możliwe, czy możesz zrobić z nim coś użytecznego (rzeczywiste pole int32 jest prywatne)?

Edit: Ok, aby uczynić go nieco bardziej jasne: to pytanie nie ma nic o int jest alias do System.Int32. Można wziąć podany przykład, zamienić int na System.Int32 i pominąć pierwszy akapit za przykładem. Prawdziwe pytanie dotyczy możliwości posiadania valuetype [mscorlib]System.Int32 a w swoim kodzie IL zamiast tylko int32 a.

+1

'int a = new int();' jest tym samym, co 'System.Int32 a = new System.Int32();'. To tylko cukier syntaktyczny. Obie będą reprezentowane wewnętrznie jako 'int32'. Mimo że w CLR występuje garść struktur, które są obsługiwane "magicznie", jest to lepsze niż w niektórych innych językach, takich jak Java, gdzie pobieranie wszystkich dodatków wymaga boksowania/rozpakowywania. –

Odpowiedz

2

więc rozważyć następujący kod:

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

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

w 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 jest używany tylko do boksu/unboxing. Gdy zmienna jest w stosie, zawsze jest int32.


Od Int32 and int:

To może być pomocne, aby myśleć o System.Int32 jako rodzaj cienia dla Int32.

Następujący kod C#:

int x = 0; 
x.ToString(); 

Czy to w IL:

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

Wskazówki, jak to przepuszczanie Int32 na pozór niezgodnych System.Int32 struktury. Silnik pozwala na to, aby został rozpoznany jako niezmieniony, aby rozpoznać System.Int32 jako cień typu int32.

+0

Można przesuwać dalej z przykładem boksu: 'int a = 5; int b = 10; Obiekt oa = a; Obiekt ob = b; Int32 с = ((Int32) oa) + ((Int32) ob); ' Jeśli zbadasz IL, zobaczysz: ' 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' Tak, jak 'add' współpracuje z prymitywów CLR można wnioskują, że nie ma czegoś takiego jak "unboxed System.Int32" i "System.Int32" jest używany tylko do tworzenia obiektów typu. –

0

CLR ma zestaw typów pierwotnych, które są zdefiniowane przez wyliczenie CorElementType. http://msdn.microsoft.com/en-us/library/ms232600.aspx

Opcodes add, sub, div, rem, etc działają na tych typach. JIT zamieni je w kod szybkiego montażu. Nie możesz zdefiniować nowych. Możesz spojrzeć na kod generowany przy użyciu SOS, jeśli jesteś zainteresowany.

Jeśli chcesz emulować język, możesz użyć przeciążenia operatora w swoim typie. http://msdn.microsoft.com/en-us/library/8edha89s.aspx

1

int32 vs int (== System.Int32)

Z Understanding .NET Primitive Types:

Int32 jest CLR pierwotnej. Następnie w FCL jest reprezentowany przez strukturę System32. Wartość całkowita System.Int32 jest utrzymywana na jego wartość m_value, a wiele metod związanych z liczbą całkowitą jest zdefiniowanych w System.Int32.

W języku C# int jest tylko aliasem dla System.Int32, obsługiwanym przez kompilator C# . Nie ma więc zależności między int i System.Int32

Od IL "The Language of CLR":

Wszystkie kompilatory pod .NET będzie generować Intermediate Language nieważne jaki język jest używany do opracowania aplikacji. W rzeczywistości CLR nie będzie świadomy języka używanego do tworzenia aplikacji. Wszystkie kompilatory języka wygenerują jednolity, wspólny język o nazwie Intermediate Język.

Tak, w języku C# System.Int32 jest to, co mamy dla IL int32. Nie znam sposobu pracy z IL bezpośrednio z kodu C#, a właściwie nie widzę żadnego powodu.

Jest on: Tool to allow inline IL in C#/VB.Net


chodzi int vs System.Int32:

post na int System.Int32 na SO: C#, int or Int32? Should I care?

W MSDN:

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

To wszystko jest takie samo:

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

int jest niejako cukier syntaktyczny ... faktycznie jest System.Int32

Poza spojrzeć Specyfikacja języka C# 4.1.4 Typy proste:

C# udostępnia zestaw predefiniowanych typów struktur nazywanych typami prostymi. Proste typy są identyfikowane przez zarezerwowanych słów, ale te zastrzeżone słowa są po prostu aliasy dla predefiniowanych struct typów w przestrzeni nazw systemu, jak opisano w tabeli

gdzie

  1. krótki => System .Int16
  2. int => System.Int32
  3. długo => System.Int64

i tak dalej.

+0

Ale 'int32' i' Int32' nie są takie same. Nie ma czegoś takiego jak "int32" w języku C#. –

+0

przeczytaj: http://weblogs.asp.net/dixin/archive/2007/12/20/understanding-net-primitive-types.aspx – horgh

+0

Przyjemny artykuł. Ale wyraźnie stwierdza, że ​​napisałem powyżej: 'Int32' i' int32' nie są takie same (również 'int'! =' Int32'). Nie kłócę się tutaj o 'Int32' i' int'. Pytanie dotyczy 'Int32' i' int32'. –

Powiązane problemy