Saya merasa aneh bahwa Anda null.ToString()diberi nama wtf. Mengapa itu mengejutkan Anda? Anda tidak dapat memanggil metode contoh saat Anda tidak memiliki alasan untuk memanggilnya.
BoltClock
11
@BoltClock: Tentu saja mungkin memanggil metode instance pada instance nol Hanya tidak mungkin dalam C #, tetapi sangat valid pada CLR :)
leppie
1
Jawaban yang berkaitan dengan String.Compat hampir benar. Bahkan, contoh spesifik dalam pertanyaan adalah salah satu pelipatan konstan , dan nol di baris pertama dihilangkan oleh kompiler - yaitu mereka tidak pernah dievaluasi saat runtime karena mereka tidak ada lagi - kompiler telah menghapusnya. Saya menulis sedikit monolog tentang semua aturan untuk penggabungan dan pelipatan konstan dari String di sini untuk info lebih lanjut: stackoverflow.com/questions/9132338/… .
Chris Shain
77
Anda dapat menambahkan apa pun ke string tetapi Anda tidak dapat membuat string dari ketiadaan.
RGB
Apakah pernyataan kedua tidak valid? class null_extension { String ToString( Object this arg ) { return ToString(arg); } }
Operator biner + melakukan penggabungan string ketika satu atau kedua operan bertipe string.
Jika operan penggabungan string adalah null, string kosong diganti. Jika tidak, argumen non-string apa pun akan dikonversi ke representasi string dengan memanggil ToStringmetode virtual yang diwarisi dari objek tipe.
Jika ToStringkembali null, string kosong diganti.
Alasan kesalahan di detik adalah:
null (C # Referensi) - Kata kunci nol adalah literal yang mewakili referensi nol, yang tidak merujuk ke objek apa pun. null adalah nilai default variabel tipe referensi.
Apakah ini akan berhasil? var wtf = ((String)null).ToString();Saya bekerja di Jawa baru-baru ini di mana casting null's mungkin, sudah lama sejak saya bekerja dengan C #.
Jochem
14
@Jochem: Anda masih mencoba memanggil metode pada objek nol, jadi saya kira tidak. Anggap saja sebagai null.ToString()vs ToString(null).
Svish
@Vish ya, sekarang saya pikirkan lagi, itu adalah objek nol, jadi Anda benar, itu tidak akan berfungsi. Ini tidak akan di Jawa juga: pengecualian pointer nol. Lupakan. Tnx untuk balasan Anda! [sunting: mengujinya di Java: NullPointerException. Dengan perbedaan yang dikompilasi oleh cast, tanpa cast tidak].
Jochem
umumnya tidak ada alasan untuk sengaja melakukan concat atau ToString kata kunci null. Jika Anda membutuhkan string kosong gunakan string.Empty. jika Anda perlu memeriksa apakah variabel string adalah nol, Anda dapat menggunakan (myString == null) atau string.IsNullOrEmpty (myString). Atau untuk mengubah variabel string nol menjadi string.Empty gunakan myNewString = (myString == null ?? string.Empty)
csauve
@Jochem casting itu akan membuatnya dikompilasi tetapi memang akan melempar NullReferenceException saat runtime
jeroenh
108
Karena +operator di C # diterjemahkan secara internal String.Concat, yang merupakan metode statis. Dan metode ini terjadi untuk memperlakukan nullseperti string kosong. Jika Anda melihat sumber String.Concatdi Reflector, Anda akan melihatnya:
// while looping through the parameters
strArray[i]=(str ==null)?Empty: str;// then concatenate that string array
Tidak ada operator + di kelas String .. Jadi apakah kompiler menerjemahkan ke String.Compat?
superlogis
@superlogical Ya, itulah yang dilakukan oleh kompiler. Jadi sebenarnya, +operator pada string dalam C # hanyalah gula sintaksis untuk String.Concat.
Botz3000
Menambah itu: Kompilator secara otomatis mengambil kelebihan dari Concat yang paling masuk akal. Kelebihan yang tersedia adalah 1, 2 atau 3 parameter objek, 4 parameter objek + __arglistdan paramsversi array objek.
Wormbo
Apa array string yang sedang dimodifikasi di sana? Apakah Concatselalu membuat array baru string non-null bahkan ketika diberi array string non-null, atau ada hal lain yang terjadi?
supercat
@supercat Array yang dimodifikasi adalah array baru, yang kemudian diteruskan ke metode pembantu pribadi. Anda dapat melihat kode sendiri menggunakan reflektor.
Botz3000
29
The sampel pertama akan diterjemahkan menjadi:
var bob =String.Concat("abc123",null,null,null,"abs123");
Itu Concat Metode pemeriksaan input dan menerjemahkan null sebagai string kosong
The sampel kedua akan diterjemahkan menjadi:
var wtf =((object)null).ToString();
Jadi nullpengecualian referensi akan dihasilkan di sini
Saya baru saja :) ((object)null).ToString()=> AccessViolation((object)1 as string).ToString()=>NullReference
leppie
1
Saya sudah mendapat NullReferenceException. DN 4.0
Viacheslav Smityukh
Menarik. Ketika saya memasukkan ke ((object)null).ToString()dalam try/catchsaya NullReferenceExceptionjuga mendapatkan .
leppie
3
@Ippie kecuali yang tidak membuang AccessViolation (mengapa?) - NullReferenceException di sini.
jeroenh
11
Bagian pertama dari kode Anda diperlakukan seperti itu di String.Concat,
yang disebut oleh kompilator C # saat Anda menambahkan string. " abc" + nullditerjemahkan ke String.Concat("abc", null),
dan secara internal, metode itu diganti nulldengan String.Empty. Jadi, itu sebabnya bagian pertama kode Anda tidak membuang pengecualian. itu seperti
var bob ="abc"+string.Empty+string.Empty+string.Empty+"123";//abc123
Dan di bagian ke-2 dari kode Anda melemparkan pengecualian karena 'nol' bukan objek, kata kunci nol adalah literal yang mewakili referensi nol , yang tidak merujuk ke objek apa pun. null adalah nilai default variabel tipe referensi.
Dan ' ToString()' adalah metode yang dapat dipanggil oleh instance dari suatu objek tetapi tidak secara literal.
String.Emptytidak sama dengan null. Itu hanya diperlakukan dengan cara yang sama dalam beberapa metode seperti String.Concat. Misalnya, jika Anda memiliki variabel string diatur ke null, C # tidak akan menggantinya dengan String.Emptyjika Anda mencoba memanggil metode di dalamnya.
Botz3000
3
Hampir. nulltidak diperlakukan seperti String.Emptyoleh C #, itu hanya diperlakukan seperti itu di String.Concat, yang adalah apa yang disebut kompiler C # ketika Anda menambahkan string. "abc" + nullditerjemahkan ke String.Concat("abc", null), dan secara internal, metode itu diganti nulldengan String.Empty. Bagian kedua sepenuhnya benar.
Botz3000
9
Dalam kerangka COM yang mendahului. Net, itu perlu untuk setiap rutin yang menerima string untuk membebaskannya ketika sudah selesai dengan itu. Karena itu sangat umum untuk string kosong untuk masuk dan keluar dari rutinitas, dan karena berusaha untuk "membebaskan" pointer nol didefinisikan sebagai operasi tidak melakukan apa-apa yang sah, Microsoft memutuskan untuk memiliki string pointer kosong mewakili string kosong.
Untuk memungkinkan kompatibilitas dengan COM, banyak rutin di .net akan menafsirkan objek nol sebagai representasi hukum sebagai string kosong. Dengan beberapa perubahan kecil .net dan bahasanya (yang paling memungkinkan anggota contoh untuk menunjukkan "jangan dipanggil sebagai virtual"), Microsoft dapat membuat nullobjek dengan tipe String yang dinyatakan berperilaku lebih seperti string kosong. Jika Microsoft telah melakukan itu, itu juga harus membuat Nullable<T>pekerjaan agak berbeda (sehingga memungkinkan - Nullable<String>sesuatu yang seharusnya mereka lakukan IMHO) dan / atau menentukan NullableStringjenis yang sebagian besar akan dipertukarkan dengan String, tetapi yang tidak akan menganggap nullsebagai string kosong yang valid.
Seperti adanya, ada beberapa konteks di mana a nullakan dianggap sebagai string kosong yang sah dan yang lainnya tidak. Bukan situasi yang sangat membantu, tetapi yang harus diperhatikan oleh programmer. Secara umum, ekspresi formulir stringValue.someMemberakan gagal jika stringValueada null, tetapi sebagian besar metode kerangka kerja dan operator yang menerima string sebagai parameter akan dianggap nullsebagai string kosong.
'+'adalah operator infiks. Seperti halnya operator apa pun, itu benar-benar memanggil metode. Anda dapat membayangkan versi non-infiks"wow".Plus(null) == "wow"
Pelaksana telah memutuskan sesuatu seperti ini ...
Sungguh, ini lebih seperti var bob = Plus(Plus(Plus(Plus("abc",null),null),null),"123");. Kelebihan operator adalah metode statis di hati mereka: msdn.microsoft.com/en-us/library/s53ehcz3(v=VS.71).aspx Jika tidak, var bob = null + "abc";atau khususnya string bob = null + null;tidak akan valid.
Ben Mosher
Anda benar, saya hanya merasa saya akan terlalu membingungkan jika saya menjelaskannya seperti itu.
Nigel Thorne
3
Saya kira karena itu literal yang tidak merujuk ke objek apa pun. ToString()membutuhkan sebuah object.
Seseorang berkata di utas diskusi ini bahwa Anda tidak dapat membuat string dari ketiadaan.
(yang merupakan ungkapan yang bagus seperti yang saya pikirkan). Tapi ya - Anda dapat :-), seperti yang ditunjukkan contoh berikut:
var x =null+(string)null;var wtf = x.ToString();
berfungsi dengan baik dan tidak membuang pengecualian sama sekali. Satu-satunya perbedaan adalah bahwa Anda perlu membuang salah satu nulls ke dalam string - jika Anda menghapus cast (string) , maka contohnya masih mengkompilasi, tetapi melempar pengecualian run-time: "Operator '+' ambigu pada operan dari ketik '<null>' dan '<null>' ".
NB Dalam contoh kode di atas, nilai x tidak nol seperti yang Anda harapkan, itu sebenarnya adalah string kosong setelah Anda memasukkan salah satu operan ke dalam string.
Fakta lain yang menarik adalah bahwa dalam C # /. NET cara nulldiperlakukan tidak selalu sama jika Anda menganggap tipe data yang berbeda. Sebagai contoh:
int? x =1;// string x = "1";
x = x +null+null;Console.WriteLine((x==null)?"<null>": x.ToString());
Mengenai baris pertama dari cuplikan kode: If xadalah variabel integer yang dapat dibatalkan (misint? ) yang berisi nilai 1, maka Anda mendapatkan hasilnya <null>kembali. Jika itu adalah string (seperti yang ditunjukkan dalam komentar) dengan nilai "1", maka Anda akan "1"kembali daripada <null>.
NB Juga menarik: Jika Anda menggunakan var x = 1;untuk baris pertama, maka Anda mendapatkan kesalahan runtime. Mengapa? Karena tugas akan mengubah variabel xmenjadi tipe data int, yang tidak dapat dibatalkan. Compiler tidak berasumsi di int?sini, dan karenanya gagal di baris ke-2 di mananull ditambahkan.
Menambahkan nullke string diabaikan saja. null(dalam contoh kedua Anda) bukan turunan dari objek apa pun, jadi ia bahkan tidak memiliki ToString()metode. Itu hanya literal.
Karena tidak ada perbedaan antara string.Emptydan nullketika Anda memainkan string. Anda dapat melewatkan null string.Formatjuga. Tetapi Anda mencoba memanggil metode null, yang akan selalu menghasilkan a NullReferenceExceptiondan karenanya menghasilkan kesalahan kompiler.
Jika karena alasan tertentu Anda benar-benar ingin melakukannya, Anda dapat menulis metode ekstensi, yang memeriksa nulldan kemudian kembali string.Empty. Tetapi ekstensi seperti itu seharusnya hanya digunakan jika benar-benar diperlukan (menurut saya).
Secara umum: Ini mungkin atau mungkin tidak valid menerima null sebagai parameter tergantung pada spesifikasi, tetapi selalu tidak valid untuk memanggil metode pada null.
Itu dan topik lain mengapa operan + operator bisa nol jika ada string. Ini adalah hal yang agak VB (maaf guys) untuk membuat hidup programmer lebih mudah, atau seandainya programmer tidak dapat menangani nulls. Saya sepenuhnya tidak setuju dengan spesifikasi ini. 'tidak diketahui' + 'apapun' harus tetap 'tidak diketahui' ...
null.ToString()
diberi namawtf
. Mengapa itu mengejutkan Anda? Anda tidak dapat memanggil metode contoh saat Anda tidak memiliki alasan untuk memanggilnya.class null_extension { String ToString( Object this arg ) { return ToString(arg); } }
Jawaban:
Alasan yang pertama bekerja:
Dari MSDN :
Informasi lebih lanjut tentang + operator biner :
Alasan kesalahan di detik adalah:
null (C # Referensi) - Kata kunci nol adalah literal yang mewakili referensi nol, yang tidak merujuk ke objek apa pun. null adalah nilai default variabel tipe referensi.
sumber
wtf = ((String)null).ToString();
Saya bekerja di Jawa baru-baru ini di mana casting null's mungkin, sudah lama sejak saya bekerja dengan C #.null.ToString()
vsToString(null)
.Karena
+
operator di C # diterjemahkan secara internalString.Concat
, yang merupakan metode statis. Dan metode ini terjadi untuk memperlakukannull
seperti string kosong. Jika Anda melihat sumberString.Concat
di Reflector, Anda akan melihatnya:(MSDN menyebutkannya juga: http://msdn.microsoft.com/en-us/library/k9c94ey1.aspx )
Di sisi lain,
ToString()
apakah metode instance, yang tidak dapat Anda panggilnull
(jenis apa yang harus digunakannull
?).sumber
+
operator pada string dalam C # hanyalah gula sintaksis untukString.Concat
.__arglist
danparams
versi array objek.Concat
selalu membuat array baru string non-null bahkan ketika diberi array string non-null, atau ada hal lain yang terjadi?The sampel pertama akan diterjemahkan menjadi:
Itu
Concat
Metode pemeriksaan input dan menerjemahkan null sebagai string kosongThe sampel kedua akan diterjemahkan menjadi:
Jadi
null
pengecualian referensi akan dihasilkan di sinisumber
AccessViolationException
akan dilempar :)((object)null).ToString()
=>AccessViolation
((object)1 as string).ToString()
=>NullReference
((object)null).ToString()
dalamtry/catch
sayaNullReferenceException
juga mendapatkan .Bagian pertama dari kode Anda diperlakukan seperti itu di
String.Concat
,yang disebut oleh kompilator C # saat Anda menambahkan string. "
abc" + null
diterjemahkan keString.Concat("abc", null)
,dan secara internal, metode itu diganti
null
denganString.Empty
. Jadi, itu sebabnya bagian pertama kode Anda tidak membuang pengecualian. itu sepertiDan di bagian ke-2 dari kode Anda melemparkan pengecualian karena 'nol' bukan objek, kata kunci nol adalah literal yang mewakili referensi nol , yang tidak merujuk ke objek apa pun. null adalah nilai default variabel tipe referensi.
Dan '
ToString()
' adalah metode yang dapat dipanggil oleh instance dari suatu objek tetapi tidak secara literal.sumber
String.Empty
tidak sama dengannull
. Itu hanya diperlakukan dengan cara yang sama dalam beberapa metode sepertiString.Concat
. Misalnya, jika Anda memiliki variabel string diatur kenull
, C # tidak akan menggantinya denganString.Empty
jika Anda mencoba memanggil metode di dalamnya.null
tidak diperlakukan sepertiString.Empty
oleh C #, itu hanya diperlakukan seperti itu diString.Concat
, yang adalah apa yang disebut kompiler C # ketika Anda menambahkan string."abc" + null
diterjemahkan keString.Concat("abc", null)
, dan secara internal, metode itu digantinull
denganString.Empty
. Bagian kedua sepenuhnya benar.Dalam kerangka COM yang mendahului. Net, itu perlu untuk setiap rutin yang menerima string untuk membebaskannya ketika sudah selesai dengan itu. Karena itu sangat umum untuk string kosong untuk masuk dan keluar dari rutinitas, dan karena berusaha untuk "membebaskan" pointer nol didefinisikan sebagai operasi tidak melakukan apa-apa yang sah, Microsoft memutuskan untuk memiliki string pointer kosong mewakili string kosong.
Untuk memungkinkan kompatibilitas dengan COM, banyak rutin di .net akan menafsirkan objek nol sebagai representasi hukum sebagai string kosong. Dengan beberapa perubahan kecil .net dan bahasanya (yang paling memungkinkan anggota contoh untuk menunjukkan "jangan dipanggil sebagai virtual"), Microsoft dapat membuat
null
objek dengan tipe String yang dinyatakan berperilaku lebih seperti string kosong. Jika Microsoft telah melakukan itu, itu juga harus membuatNullable<T>
pekerjaan agak berbeda (sehingga memungkinkan -Nullable<String>
sesuatu yang seharusnya mereka lakukan IMHO) dan / atau menentukanNullableString
jenis yang sebagian besar akan dipertukarkan denganString
, tetapi yang tidak akan menganggapnull
sebagai string kosong yang valid.Seperti adanya, ada beberapa konteks di mana a
null
akan dianggap sebagai string kosong yang sah dan yang lainnya tidak. Bukan situasi yang sangat membantu, tetapi yang harus diperhatikan oleh programmer. Secara umum, ekspresi formulirstringValue.someMember
akan gagal jikastringValue
adanull
, tetapi sebagian besar metode kerangka kerja dan operator yang menerima string sebagai parameter akan dianggapnull
sebagai string kosong.sumber
'+'
adalah operator infiks. Seperti halnya operator apa pun, itu benar-benar memanggil metode. Anda dapat membayangkan versi non-infiks"wow".Plus(null) == "wow"
Pelaksana telah memutuskan sesuatu seperti ini ...
Jadi .. teladan Anda menjadi
yang sama dengan
Tanpa titik tidak null menjadi string. Jadi
null.ToString()
tidak ada bedanyanull.VoteMyAnswer()
. ;)sumber
var bob = Plus(Plus(Plus(Plus("abc",null),null),null),"123");
. Kelebihan operator adalah metode statis di hati mereka: msdn.microsoft.com/en-us/library/s53ehcz3(v=VS.71).aspx Jika tidak,var bob = null + "abc";
atau khususnyastring bob = null + null;
tidak akan valid.Saya kira karena itu literal yang tidak merujuk ke objek apa pun.
ToString()
membutuhkan sebuahobject
.sumber
Seseorang berkata di utas diskusi ini bahwa Anda tidak dapat membuat string dari ketiadaan. (yang merupakan ungkapan yang bagus seperti yang saya pikirkan). Tapi ya - Anda dapat :-), seperti yang ditunjukkan contoh berikut:
berfungsi dengan baik dan tidak membuang pengecualian sama sekali. Satu-satunya perbedaan adalah bahwa Anda perlu membuang salah satu nulls ke dalam string - jika Anda menghapus cast (string) , maka contohnya masih mengkompilasi, tetapi melempar pengecualian run-time: "Operator '+' ambigu pada operan dari ketik '<null>' dan '<null>' ".
NB Dalam contoh kode di atas, nilai x tidak nol seperti yang Anda harapkan, itu sebenarnya adalah string kosong setelah Anda memasukkan salah satu operan ke dalam string.
Fakta lain yang menarik adalah bahwa dalam C # /. NET cara
null
diperlakukan tidak selalu sama jika Anda menganggap tipe data yang berbeda. Sebagai contoh:Mengenai baris pertama dari cuplikan kode: If
x
adalah variabel integer yang dapat dibatalkan (misint?
) yang berisi nilai1
, maka Anda mendapatkan hasilnya<null>
kembali. Jika itu adalah string (seperti yang ditunjukkan dalam komentar) dengan nilai"1"
, maka Anda akan"1"
kembali daripada<null>
.NB Juga menarik: Jika Anda menggunakan
var x = 1;
untuk baris pertama, maka Anda mendapatkan kesalahan runtime. Mengapa? Karena tugas akan mengubah variabelx
menjadi tipe dataint
, yang tidak dapat dibatalkan. Compiler tidak berasumsi diint?
sini, dan karenanya gagal di baris ke-2 di mananull
ditambahkan.sumber
Menambahkan
null
ke string diabaikan saja.null
(dalam contoh kedua Anda) bukan turunan dari objek apa pun, jadi ia bahkan tidak memilikiToString()
metode. Itu hanya literal.sumber
Karena tidak ada perbedaan antara
string.Empty
dannull
ketika Anda memainkan string. Anda dapat melewatkan nullstring.Format
juga. Tetapi Anda mencoba memanggil metodenull
, yang akan selalu menghasilkan aNullReferenceException
dan karenanya menghasilkan kesalahan kompiler.Jika karena alasan tertentu Anda benar-benar ingin melakukannya, Anda dapat menulis metode ekstensi, yang memeriksa
null
dan kemudian kembalistring.Empty
. Tetapi ekstensi seperti itu seharusnya hanya digunakan jika benar-benar diperlukan (menurut saya).sumber
Secara umum: Ini mungkin atau mungkin tidak valid menerima null sebagai parameter tergantung pada spesifikasi, tetapi selalu tidak valid untuk memanggil metode pada null.
Itu dan topik lain mengapa operan + operator bisa nol jika ada string. Ini adalah hal yang agak VB (maaf guys) untuk membuat hidup programmer lebih mudah, atau seandainya programmer tidak dapat menangani nulls. Saya sepenuhnya tidak setuju dengan spesifikasi ini. 'tidak diketahui' + 'apapun' harus tetap 'tidak diketahui' ...
sumber