Menu

Optional Parameter dan Named Argument C#: Default dan Aturan

Cara kerja optional parameter dan named argument di C#: nilai default dan aturan konstanta compile-time, urutan parameter, melewati argumen lewat namanya, optional parameter vs overload, atribut caller info, dan jebakan versioning karena nilai default ditanam di kode pemanggil.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Optional parameter punya nilai default di deklarasi method, jadi pemanggil boleh tidak menuliskannya. Named argument mengirim nilai berdasarkan nama parameter, bukan posisinya. Bersama-sama, keduanya membuat satu method bisa melayani banyak bentuk pemanggilan tanpa setumpuk overload.

Output:

to ana@mail.com: (no subject), retries 3
to ben@mail.com: Invoice #1042, retries 3
to cy@mail.com: (no subject) [URGENT], retries 3
to dev@mail.com: Build failed, retries 0

Pemanggilan ketiga melewati subject dan mengatur urgent lewat namanya; tanpa named argument, pemanggilan itu harus mengirim "(no subject)" lagi hanya untuk sampai ke posisi ketiga. Pemanggilan terakhir mengirim setiap argumen lewat namanya dalam urutan yang berbeda dari deklarasinya, dan itu sah.

Aturan untuk nilai default

Nilai default harus sesuatu yang bisa dihitung oleh compiler:

  • sebuah konstanta (3, "INFO", true, 1.5m, field const, member enum)
  • null untuk reference type atau nullable type
  • default(T), atau new T() untuk value type T

Apa pun yang dievaluasi saat program berjalan akan ditolak. Kasus klasiknya adalah tanggal:

static void Schedule(string task, DateTime at = DateTime.Now) { }
// error CS1736: Default parameter value for 'at' must be a compile-time constant

Cara standar untuk mengatasinya adalah parameter nullable dengan null sebagai nilai default, lalu nilainya ditentukan di badan method:

Output:

backup at 2026-01-01 09:00, tags: 0
report at 2026-03-15 18:30, tags: 0
deploy at 2026-01-01 09:00, tags: 2

Trik yang sama berlaku untuk koleksi: nilai default new List<string>() bukan konstanta, jadi beri default null lalu buat list-nya di dalam method. Cara ini juga menghindari bug ala Python berupa nilai default mutable yang dipakai bersama, yang dicegah C# dengan hanya mengizinkan konstanta.

Aturan urutan

Parameter wajib ditulis pertama, optional parameter setelahnya, dan array params (kalau ada) di paling akhir:

static void Log(string message, string level = "INFO", params string[] tags) { }   // OK

static void Log(string level = "INFO", string message) { }
// error CS1737: Optional parameters must appear after all required parameters

Parameter ref dan out tidak bisa dibuat opsional.

Di sisi pemanggil, argumen berdasarkan posisi mengisi parameter dari awal. Named argument bisa menyusul dalam urutan apa pun. Sejak C# 7.2, named argument juga boleh muncul sebelum argumen berdasarkan posisi, tapi hanya saat ia berada di posisinya sendiri (SendEmail("a@b.c", subject: "Hi", true)); di versi yang lebih lama, semua named argument harus ditulis di akhir. Tidak menuliskan parameter wajib, bahkan saat menyebut nama parameter lain, adalah error saat compile.

Named argument supaya mudah dibaca

Named argument berguna bahkan saat tidak ada yang opsional. Literal true, false, null dan angka begitu saja tidak memberi tahu apa pun di tempat pemanggilan:

ResizeImage(photo, 800, 600, true, false);                                   // which is which?
ResizeImage(photo, width: 800, height: 600, keepAspect: true, upscale: false);

Mengganti nama parameter menjadi perubahan yang merusak bagi pemanggil yang memakai nama itu, dan ini perlu diingat di library publik.

Optional parameter vs overload

Sebelum C# 4, fleksibilitas yang sama butuh satu overload untuk setiap kombinasi. Optional parameter meringkasnya menjadi satu method:

// overloads
static void Connect(string host) => Connect(host, 443);
static void Connect(string host, int port) => Connect(host, port, 30);
static void Connect(string host, int port, int timeoutSeconds) { /* ... */ }

// one method with optional parameters
static void Connect(string host, int port = 443, int timeoutSeconds = 30) { /* ... */ }

Saat keduanya ada, overload resolution lebih memilih kandidat yang tidak perlu mengisi nilai default apa pun:

Output:

Greet()
Greet(string) with Lena

Greet() cocok dengan kedua method, dan compiler memilih yang tidak punya optional parameter yang dilewatkan. Mencampur kedua teknik pada nama yang sama biasanya menghasilkan pemanggilan yang tujuannya sulit ditebak, jadi pilih salah satu untuk setiap method.

Pilih overload saat variasinya butuh kode yang berbeda atau tipe parameter yang berbeda, dan optional parameter saat variasinya hanya berbeda pada nilai default.

Nilai default ditanam di kode pemanggil

Nilai default tidak dicari saat program berjalan. Compiler menyalinnya ke setiap tempat pemanggilan saat kode pemanggilnya di-compile. Connect("api.shop.com") di-compile menjadi Connect("api.shop.com", 443, 30).

Hal ini berakibat pada library. Misalkan versi 1 sebuah package merilis Connect(string host, int timeoutSeconds = 30), lalu versi 2 mengubah default-nya menjadi 10. Aplikasi yang di-compile dengan versi 1 tetap mengirim 30 setelah kamu memasang DLL versi 2, sampai aplikasi itu sendiri di-compile ulang. Menambahkan optional parameter baru ke method publik yang sudah ada juga merusak pemanggil yang sudah di-compile, karena signature method-nya berubah dan mereka masih mencari yang lama (MissingMethodException saat program berjalan).

Di dalam satu aplikasi yang di-compile secara keseluruhan, hal ini tidak pernah menjadi masalah. Untuk API publik di package NuGet, overload (yang menyimpan nilai default di dalam library) atau default null yang ditentukan di badan method bisa menghindari masalah ini.

Nilai default dan tipe yang dideklarasikan

Aturan compile-time yang sama berarti saat sebuah interface dan sebuah class sama-sama mendeklarasikan nilai default, nilai default-nya diambil dari tipe variabel yang kamu pakai untuk memanggil, bukan dari objeknya:

Output:

printing "report" x5
printing "report" x1

Objek yang sama, dua nilai default yang berbeda. Jaga agar nilai default sama persis antara interface dan implementasinya, atau deklarasikan hanya di satu tempat.

Atribut caller information

Optional parameter juga menjadi dasar atribut caller info di System.Runtime.CompilerServices. Compiler mengisinya dengan detail dari tempat pemanggilan:

Output:

[Main:18] starting
[SaveOrder:13] order saved

Dengan cara inilah library logging mencatat asal sebuah pesan tanpa perlu diketik oleh pemanggil, dan dengan cara ini juga implementasi INotifyPropertyChanged mendapatkan nama property-nya. [CallerFilePath] menambahkan path file sumber dengan cara yang sama.

Pertanyaan yang sering diajukan

Bagaimana cara membuat parameter opsional di C#?

Beri nilai default di deklarasinya: static void Log(string message, string level = "INFO"). Pemanggil lalu bisa menulis Log("started") atau Log("failed", "ERROR"). Optional parameter harus ditulis setelah semua parameter wajib, dan nilai default-nya harus berupa konstanta compile-time.

Apa itu named argument di C#?

Argumen yang dikirim bersama nama parameternya: SendEmail(to: "ana@mail.com", urgent: true). Named argument membuatmu bisa melewati optional parameter di tengah, mengirim argumen dalam urutan apa pun, dan membuat pemanggilan dengan literal true/false atau angka langsung terbaca jelas.

Kenapa saya tidak bisa memakai DateTime.Now sebagai nilai default parameter?

Nilai default harus berupa konstanta compile-time, sedangkan DateTime.Now dihitung saat program berjalan, jadi compiler melaporkan CS1736, Default parameter value for 'at' must be a compile-time constant. Pakai parameter nullable sebagai gantinya: DateTime? at = null, lalu DateTime time = at ?? DateTime.Now; di badan method.

Sebaiknya pakai optional parameter atau overload method di C#?

Optional parameter lebih sederhana saat variasinya hanya berbeda pada nilai default. Overload lebih baik saat variasinya butuh logika atau tipe yang berbeda, dan di library publik, karena nilai default di-compile ke setiap pemanggil dan mengubahnya nanti tidak akan sampai ke kode yang sudah di-compile.

Apa arti "Optional parameters must appear after all required parameters"?

Error CS1737: parameter yang punya nilai default diikuti parameter yang tidak punya. Pindahkan parameter wajib ke depan: (string to, bool urgent = false), bukan (bool urgent = false, string to). Setelah sebuah optional parameter, hanya optional parameter lain atau array params yang boleh menyusul.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai