Tidak dapat menggunakan String.Empty sebagai nilai default untuk parameter opsional

89

Saya membaca Effective C # oleh Bill Wagner. Di Item 14 - Minimize Duplicate Initialization Logic , dia menunjukkan contoh berikut menggunakan fitur parameter opsional baru dalam konstruktor:

public MyClass(int initialCount = 0, string name = "")

Perhatikan bahwa ia menggunakan ""bukannya string.Empty.
Dia berkomentar:

Anda akan melihat [dalam contoh di atas] bahwa konstruktor kedua menetapkan "" untuk nilai default pada parameter name , bukan yang lebih umum string.Empty. Itu karena string.Emptybukan konstanta waktu kompilasi. Ini adalah properti statis yang ditentukan dalam kelas string. Karena ini bukan konstanta kompilasi, Anda tidak dapat menggunakannya sebagai nilai default untuk parameter.

Jika kita tidak dapat menggunakan string.Emptystatik dalam semua situasi, bukankah itu menggagalkan tujuannya? Saya pikir kami akan menggunakannya untuk memastikan bahwa kami memiliki cara yang tidak bergantung sistem untuk merujuk ke string kosong. Apakah pemahaman saya salah? Terima kasih.

UPDATE
Hanya komentar tindak lanjut. Menurut MSDN:

Setiap parameter opsional memiliki nilai default sebagai bagian dari definisinya. Jika tidak ada argumen yang dikirim untuk parameter itu, nilai default akan digunakan. Nilai default harus berupa konstanta.

Kemudian kita tidak dapat menggunakan System.Environment.NewLinekeduanya, atau menggunakan objek yang baru dibuat sebagai nilai default. Saya belum pernah menggunakan VS2010, dan ini mengecewakan!

Mikeyg36
sumber
2
Saya tidak mengetahui adanya perbedaan antara bagaimana string kosong direpresentasikan pada platform yang berbeda. Ini tidak seperti baris baru.
Tom Cabanski
Benar, aku sedang memikirkan itu, jadi apakah itu hanya terlihat lebih bagus dalam kode?
Mikeyg36
1
CLR dan bukan 'Sistem' adalah faktor penentu apakah "" adalah string kosong atau bukan. Jadi saya pikir Anda bisa dengan aman mengasumsikan "" adalah cara sistem-independen merujuk ke string pada implementasi CLR yang sesuai.
Chris Taylor
"sistem-independen"? eh, berbeda dengan "" khusus sistem? (???)
Qwertie
Menurut MSDN: Nilai bidang ini adalah string panjang-nol, "". jadi jelas tidak ada hubungannya dengan independensi platform, seperti yang ditunjukkan banyak orang. Namun tampaknya orang masih belum benar-benar tahu mengapa itu harus digunakan!
Mikeyg36

Jawaban:

66

Untuk compiler C # 2.0, hanya ada sedikit gunanya String.Empty, dan dalam banyak kasus ini adalah sebuah pesimisasi, karena compiler dapat menyebariskan beberapa referensi ""tetapi tidak dapat melakukan hal yang sama String.Empty.

Dalam C # 1.1 itu berguna untuk menghindari membuat banyak objek independen yang semuanya berisi string kosong, tapi hari-hari itu sudah berlalu. ""bekerja dengan baik.

Andy Mortimer
sumber
7
Bahkan di .NET 1.1 itu tidak akan membuat "banyak" objek independen. Saya tidak dapat mengingat detail perbedaan antara 1.1 dan 2.0 dalam hal ini, tetapi tidak seperti interning literal string yang hanya diperkenalkan di 2.0.
Jon Skeet
Terimakasih atas klarifikasinya. Saya telah melihat-lihat dan saya belum menemukan ringkasan yang baik tentang perubahan di C # 2.0, meskipun saya yakin saya telah membacanya sebelumnya. Saya menemukan jawaban StackOverflow dari tahun 2008 dengan beberapa tautan ke informasi teknis lainnya. stackoverflow.com/questions/151472/…
Andy Mortimer
1
Saya akan memberikan anggukan ini, meskipun saya tidak suka mengatakan ada gunanya string. Kosong karena saya menggunakannya cukup banyak. Saya merasa itu terlihat lebih bersih, meskipun itu adalah pendapat pribadi saya. Ada banyak tempat string.Empty tidak dapat digunakan, dan saya tidak memiliki masalah menggunakan "" dalam kasus tersebut
xximjasonxx
15
Saya telah menemukan bahwa jauh lebih mudah untuk dengan cepat mengidentifikasi string kosong dengan String.Empty daripada melihat dua kali pada "" untuk memastikan tidak ada apostrof atau sesuatu seperti itu yang tersembunyi di dalamnya. 1 untuk penjelasannya.
NotMe
11
+1 Chris. Juga di VS, Anda benar-benar tidak dapat melakukan pencarian pada penggunaan "" (selain melakukan Find standar yang juga akan mengembalikan setiap teks yang cocok, termasuk komentar dan markup). Anda dapat melakukan pencarian pada penggunaan kode tertentu dengan string.Empty.
MutantNinjaCodeMonkey
53

Tidak ada yang menghentikan Anda untuk menentukan konstanta Anda sendiri untuk string kosong jika Anda benar-benar ingin menggunakannya sebagai nilai parameter opsional:

const string String_Empty = "";

public static void PrintString(string s = String_Empty)
{
    Console.WriteLine(s);
}

[Sebagai tambahan, salah satu alasan untuk memilih String.Emptydaripada ""secara umum, yang belum disebutkan dalam jawaban lain, adalah bahwa ada berbagai karakter Unicode (penyambung lebar-nol, dll.) Yang secara efektif tidak terlihat dengan mata telanjang. Jadi sesuatu yang terlihat seperti ""belum tentu string kosong, sedangkan dengan String.EmptyAnda tahu persis apa yang Anda gunakan. Saya tahu ini bukan sumber bug yang umum, tetapi mungkin saja.]

Matthew Strawbridge
sumber
2
Ada juga karakter pengenal yang tidak terlihat, jadi sesuatu yang terlihat seperti String_Empty belum tentu. Standar Unicode memiliki sebagian besar bab yang diabaikan tentang pertimbangan keamanan.
Jim Balter
25

Dari pertanyaan awal:

Saya pikir kami akan menggunakannya untuk memastikan bahwa kami memiliki cara yang tidak bergantung sistem untuk merujuk ke string kosong.

Dengan cara apa string kosong bervariasi dari sistem ke sistem? Itu selalu berupa string tanpa karakter! Saya akan sangat takut jika saya menemukan implementasi di mana string.Empty == ""mengembalikan false :) Ini tidak sama dengan sesuatu seperti Environment.NewLine.

Dari postingan bounty Counter Terrorist:

Saya ingin String.Empty dapat digunakan sebagai parameter default di rilis C # berikutnya. : D

Itu pasti tidak akan terjadi.

Sementara saya pribadi akan menyukai mekanisme default yang sangat berbeda juga, cara kerja parameter opsional telah ada di .NET sejak awal - dan itu selalu berarti menyematkan konstanta ke dalam metadata, sehingga kode panggilan dapat menyalin konstanta itu ke dalam panggilan situs jika tidak ada argumen yang sesuai.

Dengan string.Emptyitu sangat tidak ada gunanya - menggunakan ""akan melakukan apa yang Anda inginkan; itu yang menyakitkan untuk menggunakan literal string yang? (Saya menggunakan literal di mana-mana - saya tidak pernah menggunakan string.Empty- tapi itu argumen yang berbeda.)

Itulah yang mengejutkan saya tentang pertanyaan ini - keluhan berkisar pada sesuatu yang sebenarnya tidak menyebabkan masalah nyata. Ini lebih penting dalam kasus di mana Anda ingin default dihitung pada waktu eksekusi karena sebenarnya mungkin berbeda. Misalnya, saya bisa membayangkan kasus di mana Anda ingin dapat memanggil metode dengan DateTimeparameter dan menetapkan default ke "waktu saat ini". Saat ini, satu-satunya solusi elegan yang samar-samar saya ketahui untuk itu adalah:

public void RecordTime(string message, DateTime? dateTime = null)
{
    var realDateTime = dateTime ?? DateTime.UtcNow;
}

... tapi itu tidak selalu tepat.

Kesimpulannya:

  • Saya sangat meragukan bahwa ini akan menjadi bagian dari C #
  • Karena string.Emptyitu tidak ada gunanya
  • Untuk nilai-nilai lain yang sebenarnya tidak selalu memiliki nilai yang sama, bisa sangat menyebalkan
Jon Skeet
sumber
Ini sebenarnya cara yang baik untuk memperbaiki masalah. Hal yang sama dapat digunakan untuk membawa / menyetel variabel dependen perangkat lain seperti Environment.Newline.. Satu-satunya hal yang hilang dari contoh Anda adalah memeriksa variabel untuk null, dan memberikan pengecualian kembali ke pengembang yang mengatakan kepadanya bahwa meskipun nullable, itu tidak diterima. if(dateTime == null){ throw new ArgumentException("The dateTime parameter must be set. Nullable type used for device independent variable set.");}atau semacam itu. Tapi saya sangat suka ini! Ada peringatan lain untuk melakukannya dengan cara Anda?
MaxOvrdrv
@MaxOvrdrv: Anda tidak ingin null menjadi error - intinya adalah ketika null, Anda menghitung default. Peringatannya adalah bahwa ia tidak mengizinkan null untuk diteruskan sebagai nilai yang valid itu sendiri.
Jon Skeet
Anda sepenuhnya benar tentang itu. Salahku. - Dan ya, itu akan menjadi satu-satunya peringatan nyata bukan ... itu tidak terlalu buruk. Sekali lagi: saya sangat menyukai solusi ini! :) Terima kasih telah mempostingnya! :)
MaxOvrdrv
7

Saya tidak pernah menggunakan string. Kosong, saya tidak bisa mengerti maksudnya. Mungkin itu mempermudah orang yang benar-benar baru dalam pemrograman, tapi saya ragu itu berguna bahkan untuk itu.

Hans Olsson
sumber
2
Mungkin itu mencegah kebingungan ""dan " ", tetapi saya tidak bisa mengatakan itu " "semua yang umum.
Greg
8
Saya menyarankan siapa pun yang tidak dapat membedakan antara kebutuhan tersebut, baik kacamata yang lebih baik atau menurunkan resolusi layar mereka. Saya memiliki penglihatan yang buruk dan saya tidak ingat pernah melakukan kesalahan itu (dan saya harus bekerja dengan banyak kode yang mengandung keduanya).
Hans Olsson
2
string.Empty berguna untuk mengetahui maksud sebenarnya dari programmer tersebut. "" tidak memberi tahu apa-apa tentang niatnya, bagaimana jika pemrogram bermaksud untuk menginisialisasi variabel seperti ini "lol" tetapi lupa ... dalam hal ini ada kemungkinan dan string yang tak terbatas, Kosong berguna dan melakukan pekerjaan yang lebih baik
berguna
4

Saya pikir ide di balik string. Kosong adalah meningkatkan keterbacaan. Ini tidak seperti baris baru di mana ada perbedaan antara bagaimana itu direpresentasikan pada platform yang berbeda. Sayangnya itu tidak dapat digunakan dalam parameter default. Namun, itu tidak akan menimbulkan masalah jika Anda melakukan port antara Windows dan sesuatu seperti Mono di Linux.

Tom Cabanski
sumber
5
Saya pikir Anda mungkin benar bahwa intinya adalah bahwa beberapa orang menganggap String.Emptylebih mudah dibaca. . . secara pribadi, saya pikir itu sedikit gila. ""mungkin string paling umum yang pernah ada dan semua orang telah melihatnya jutaan kali, jadi bagaimana ini tidak terbaca? String.Emptyberguna seolah-olah ada Int32.Zero.
Tim Goodman
3

Sebagai FYI, sepertinya batasan yang sama diberlakukan pada nilai yang diteruskan ke konstruktor atribut - nilai tersebut harus konstan. Karena string.empty didefinisikan sebagai:

public static readonly string Empty

daripada konstanta aktual, ia tidak dapat digunakan.

Shawn Eavis
sumber
2

Saya menggunakan string.Emptymurni untuk keterbacaan.

Jika orang lain perlu membaca / mengubah kode saya nanti, mereka tahu bahwa saya bermaksud memeriksa atau menyetel sesuatu ke string kosong. Menggunakan just ""terkadang dapat menyebabkan bug dan kebingungan karena saya mungkin baru saja lupa meletakkan string yang saya inginkan di sana.

Sebagai contoh:

if(someString == string.Empty)
{

}

vs.

if(someString == "")
{

}

ifPernyataan pertama sepertinya jauh lebih disengaja dan dapat dibaca oleh saya. Karena ini hanya preferensi, saya benar-benar tidak melihat kereta-smash harus menggunakan ""sebagai gantinya string.Empty.

lukejkw
sumber
-2

Mungkin solusi terbaik untuk masalah ini adalah kelebihan metode ini, dengan cara ini:

public static void PrintString() 
{ 
    PrintString(string.Empty);
}
lokum09
sumber
3
Bagaimana menjawab pertanyaan di atas?
Pranav Singh
1
Bagaimana cara membantu dengan nilai default untuk parameter opsional?
lokal default