Episode ini membuka kap mesin .NET: kompilasi C# ke IL dan eksekusi oleh CLR, garbage collector, JIT, serta struktur solution dan project. Kalian juga akan memahami Generic Host dan alur konfigurasi aplikasi modern.

Di episode 1 kalian memahami sejarah dan alasan memilih .NET. Sekarang kita masuk satu level lebih dalam: bagaimana aplikasi .NET bekerja di bawah kap mesin. Episode 2 membedah arsitektur inti — kompilasi ke IL, eksekusi oleh CLR, garbage collector, JIT, sampai struktur project dan Generic Host.
Memahami arsitektur ini penting karena banyak perilaku yang kalian lihat nanti — kenapa aplikasi lambat di awal lalu cepat, kenapa ada file .csproj, kenapa konfigurasi dibaca dari beberapa sumber — semuanya berakar pada desain runtime .NET. Kalian tidak perlu hafal semua detail, tetapi harus tahu alur utamanya.
Bahasa C# tidak langsung menjadi kode mesin. Compiler mengubah C# menjadi IL (Intermediate Language) dalam bentuk assembly. Saat aplikasi dijalankan, CLR (Common Language Runtime) memuat assembly, memvalidasi tipe, lalu menerjemahkan IL menjadi kode native lewat JIT.
Karena IL bersifat bahasa-agnostik, C#, F#, dan VB.NET semua bisa berjalan di runtime yang sama. Penerjemahan ini terjadi per metode pada saat pertama dipanggil — itulah sebabnya metode pertama biasanya paling lambat. Optimasi lanjutannya disebut tiered compilation.
Garbage collector (GC) mengelola memori secara otomatis: mengalokasikan objek di managed heap, melacak referensi, dan membebaskan objek yang tidak terpakai. Pengembang tidak perlu memanggil free atau delete — perilaku ini yang mencegah memory leak di sebagian besar aplikasi .NET.
Selain JIT (Just-In-Time), .NET mendukung AOT (Ahead-Of-Time) melalui NativeAOT: aplikasi dikompilasi penuh ke native saat publish. Hasilnya startup sangat cepat dan binary kecil, cocok untuk serverless atau edge. Keseimbangan keduanya akan dibahas di episode 15 dan 22.
Satu unit kompilasi adalah project yang digambarkan oleh file .csproj bergaya SDK. Kumpulan project yang saling terkait diorganisasi dalam solution (.sln). Berikut cara membuat keduanya dari CLI:
mkdir MyApp
cd MyApp
dotnet new sln -n MyApp
dotnet new classlib -n MyApp.Core
dotnet new console -n MyApp.Cli
dotnet sln add MyApp.Core MyApp.Cli
dotnet builddotnet new sln -n MyApp menciptakan file solution, dan dotnet sln add mendaftarkan project ke dalamnya. Setiap project punya TargetFramework — misalnya net8.0 — yang menentukan API yang tersedia. SDK-style project sangat ringkas: seluruh konfigurasi ada di satu file XML.
NuGet adalah registry paket .NET. Dependensi ditulis sebagai <PackageReference> di .csproj, dan resolusi dilakukan oleh NuGet restore. Lihat semua paket sebuah project dengan:
dotnet list packagedotnet list package menampilkan nama dan versi setiap dependensi, termasuk yang transitif. Restore otomatis terjadi saat build, sehingga file lock (mirip package-lock.json) menjaga reproduksibilitas.
Sejak .NET Core, aplikasi modern dibangun di atas Generic Host. Host adalah kontainer yang mengelola dependency injection, konfigurasi, logging, dan lifetime layanan. Anda bahkan bisa menulis API web atau worker hanya dengan template kosong:
dotnet new worker -n MyWorkerdotnet new worker -n MyWorker menciptakan project yang berisi Program.cs dengan Host.CreateApplicationBuilder. Host bertanggung jawab atas startup dan shutdown yang bersih — mulai dari background service sampai web server, semuanya hidup di dalam host yang sama.
Konfigurasi dibaca dari banyak provider secara berurutan: appsettings.json, appsettings.{Environment}.json, environment variables, hingga command line. Provider yang terakhir menimpa yang sebelumnya. Variabel lingkungan yang dipakai adalah DOTNET_ENVIRONMENT atau ASPNETCORE_ENVIRONMENT.
Info
Jangan membangun aplikasi .NET tanpa Generic Host di luar kebutuhan minimal. Host menyatukan DI, konfigurasi, dan logging sehingga kode kalian terstruktur dan mudah diuji.
Assembly adalah unit deploy yang berisi IL dan metadata tipe. Saat aplikasi berjalan, assembly loading memuat assembly ke dalam proses — mekanisme inilah yang memungkinkan plugin dan modul dimuat secara dinamis. Lihat assembly yang sedang dimuat dari dalam kode:
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
Console.WriteLine(asm.GetName().Name);
}AppDomain.CurrentDomain.GetAssemblies() mengembalikan semua assembly yang sudah dimuat proses. Detail ini penting saat mendiagnosis konflik versi library atau memutuskan strategi plugin.
Secara umum, biarkan runtime mengelola loading — melakukan intervensi manual hanya saat benar-benar diperlukan, misalnya saat menangani konflik versi antar library.
Ringkasan perjalanan kode kalian dari sumber menjadi aplikasi berjalan:
Memahami alur ini membantu kalian membaca pesan error, memperbaiki startup yang lambat, dan mendiagnosis masalah memori di episode 15. Mulai episode 3, setiap contoh akan berjalan di atas lifecycle ini.
Inti yang harus dibawa pulang:
Di episode 3 selanjutnya kita akan membahas memulai aplikasi .NET pertama — praktik langsung membuat project dengan dotnet new, memahami struktur folder Program.cs dan csproj, lalu menjalankan, membuild, dan mem-publish aplikasi console pertama kalian.