Ketika orang berbicara tentang ".net framework" mereka cenderung menggabungkan dua area utama - perpustakaan runtime dan mesin virtual yang benar-benar menjalankan kode .net.
Ketika Anda membuat perpustakaan kelas di Visual Studio di C #, DLL mengikuti format yang ditentukan - sangat kasar, ada bagian yang berisi data meta yang menjelaskan kelas apa yang termasuk di dalamnya dan fungsi apa yang mereka miliki, dll. Dan yang menjelaskan di mana dalam biner objek-objek itu ada. Format .net umum ini adalah apa yang memungkinkan perpustakaan untuk dibagikan antara bahasa .net (C #, VB.Net, F # dan lainnya) dengan mudah. Meskipun banyak .net "runtime library" ditulis dalam C # sekarang (saya percaya), Anda dapat membayangkan berapa banyak dari mereka yang bisa ditulis dalam bahasa yang tidak dikelola tetapi diatur dalam format yang ditentukan ini sehingga mereka dapat dikonsumsi oleh .net language .
"Daging" sebenarnya dari perpustakaan yang Anda buat terdiri dari CIL ("Common Intermediate Language") yang sedikit mirip dengan bahasa assembly dari .net - sekali lagi, bahasa ini adalah output umum dari semua bahasa .net, yang adalah apa membuat perpustakaan .net dapat dikonsumsi oleh bahasa .net apa pun.
Dengan menggunakan alat "ildasm.exe", yang tersedia secara bebas di Microsoft SDK (dan mungkin sudah ada di komputer Anda), Anda dapat melihat bagaimana kode C # dikonversi menjadi data meta dan IL. Saya telah memasukkan contoh di bagian bawah jawaban ini sebagai contoh.
Ketika Anda menjalankan kode .net, yang biasa terjadi adalah mesin virtual .net membaca IL itu dan memprosesnya. Ini adalah sisi lain dari .net dan, sekali lagi, Anda mungkin dapat membayangkan bahwa ini dapat dengan mudah ditulis dalam bahasa yang tidak dikelola - itu "hanya" perlu membaca instruksi VM dan menjalankannya (dan berintegrasi dengan pengumpul sampah, yang juga perlu bukan .net code).
Apa yang saya jelaskan adalah (sekali lagi, kira-kira) apa yang terjadi ketika Anda membangun sebuah executable di Visual Studio (untuk informasi lebih lanjut, saya sangat merekomendasikan buku "CLR via C # oleh Jeffrey Richter" - sangat rinci dan ditulis dengan sangat baik).
Namun, ada saat-saat Anda mungkin menulis C # yang tidak akan dieksekusi dalam lingkungan .net - misalnya, Bridge.NET "mengkompilasi" kode C # ke dalam JavaScript yang kemudian dijalankan di browser (tim yang memproduksinya telah pergi ke upaya penulisan versi pustaka runtime .net yang ditulis dalam JavaScript sehingga kekuatan dan fleksibilitas pustaka .net tersedia untuk JavaScript yang dihasilkan). Ini adalah contoh sempurna pemisahan antara C # dan .net - dimungkinkan untuk menulis C # untuk "target" yang berbeda; Anda dapat menargetkan lingkungan .net runtime (saat Anda membangun yang dapat dieksekusi) atau Anda dapat menargetkan lingkungan browser (saat Anda menggunakan Bridge.NET).
Kelas contoh (sangat) sederhana:
using System;
namespace Example
{
public class Class1
{
public void SayHello()
{
Console.WriteLine("Hello");
}
}
}
Meta data dan IL yang dihasilkan (diambil melalui ildasm.exe):
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly Example
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0A 54 65 73 74 49 4C 44 41 53 4D 00 00 ) // ...TestILDASM..
.custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0A 54 65 73 74 49 4C 44 41 53 4D 00 00 ) // ...TestILDASM..
.custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20 // ...Copyright ..
20 32 30 31 36 00 00 ) // 2016..
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 31 39 33 32 61 32 30 65 2D 61 37 36 64 // ..$1932a20e-a76d
2D 34 36 33 35 2D 62 36 38 66 2D 36 63 35 66 36 // -4635-b68f-6c5f6
32 36 36 31 36 37 62 00 00 ) // 266167b..
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0..
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1C 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 2E 32 01 // ,Version=v4.5.2.
00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 // .T..FrameworkDis
70 6C 61 79 4E 61 6D 65 14 2E 4E 45 54 20 46 72 // playName..NET Fr
61 6D 65 77 6F 72 6B 20 34 2E 35 2E 32 ) // amework 4.5.2
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module Example.dll
// MVID: {80A91E4C-0994-4773-9B73-2C4977BB1F17}
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x05DB0000
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit Example.Class1
extends [mscorlib]System.Object
{
.method public hidebysig instance void
SayHello() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Hello"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Class1::SayHello
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method Class1::.ctor
} // end of class Example.Class1
// =============================================================