Guid adalah semua 0 (nol)?

241

Saya menguji beberapa layanan WCF yang mengirim objek dengan Guids bolak-balik. Dalam kode pengujian aplikasi web saya, saya melakukan hal berikut:

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = new Guid()
});

Untuk beberapa alasan, panggilan ke Guid baru () menghasilkan Guids dengan semua 0 (nol) seperti ini:

00000000-0000-0000-0000-000000000000

Apa yang menyebabkan ini?

Didaxis
sumber
9
Setelah diedit, ini adalah pertanyaan yang sama sekali baru. Dan dibutuhkan lebih banyak informasi untuk menentukan jawaban baru.
Scott Rippey
3
Menghapus bagian yang diedit yang mengubah pertanyaan.
Didaxis
115
1 karena saya telah menggunakan pertanyaan ini untuk mencuri panduan kosong belasan kali :)
jmosesman
5
@ jmosesman, lebih baik menggunakan formulirGuid.Empty
Jonathan Moosekian
4
@ JonathanM Saya sebenarnya menggunakannya dalam skrip SQL. Posting ini baru saja muncul pertama setelah pencarian.
jmosesman

Jawaban:

428

Gunakan metode statis Guid.NewGuid()alih-alih memanggil konstruktor default.

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = Guid.NewGuid()
});
Mark Byers
sumber
18
+1 untuk jawaban yang benar serta tautan ke dokumentasi yang tepat.
ObscureRobot
109

Pelajaran dari ini:

1) Guid adalah tipe nilai, bukan tipe referensi.

2) Memanggil konstruktor default new S()pada semua tipe nilai selalu memberi Anda kembali semua-nol bentuk tipe nilai itu, apa pun itu. Secara logis sama dengan default(S).

Eric Lippert
sumber
3
Apakah itu dikompilasi ke dalam IL yang sama default(S)atau apakah ada seluk-beluk saya hilang?
konfigurator
8
@configurator: Ya. Sebenarnya, representasi internal kompiler untuk "default (S)" dan "S (baru)" adalah sama; kami tidak membedakan mereka secara internal, yang telah menyebabkan beberapa bug malang selama bertahun-tahun karena mereka sebenarnya tidak cukup identik. Misalnya, const int x = new int();tidak seharusnya legal menurut spesifikasi, tetapi const int x = default(int);; kami mengizinkan keduanya.
Eric Lippert
1
@configurator - jika Anda tertarik pada kasus sudut terkait, mungkin msmvps.com/blogs/jon_skeet/archive/2008/12/10/… juga akan menarik.
kvb
56

Coba ini sebagai gantinya:

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = new Guid.NewGuid()
});

Ini akan menghasilkan nilai Panduan 'nyata'. Ketika Anda baru tipe referensi, itu akan memberi Anda nilai default (yang dalam hal ini, semua nol untuk Guid).

Saat Anda membuat Guid baru, itu akan menginisialisasi ke semua nol, yang merupakan nilai default untuk Guid. Ini pada dasarnya sama dengan membuat int "baru" (yang merupakan tipe nilai tetapi Anda dapat melakukannya):

Guid g1;                    // g1 is 00000000-0000-0000-0000-000000000000
Guid g2 = new Guid();       // g2 is 00000000-0000-0000-0000-000000000000
Guid g3 = default(Guid);    // g3 is 00000000-0000-0000-0000-000000000000
Guid g4 = Guid.NewGuid();   // g4 is not all zeroes

Bandingkan ini dengan melakukan hal yang sama dengan int:

int i1;                     // i1 is 0
int i2 = new int();         // i2 is 0
int i3 = default(int);      // i3 is 0
JohnD
sumber
1
g1hanya akan dikompilasi sebagai bidang dan bukan sebagai variabel lokal. Juga indeks di kolom komentar Anda tidak cocok dengan baris kode yang sama
CodesInChaos
1
@CodeInChaos: Terima kasih, perbaiki komentarnya. FYI, baris g1 sebenarnya mengkompilasi ...
JohnD
3
Ini akan dikompilasi seperti apa adanya, tetapi tidak memiliki nilai yang ditentukan. Jika Anda menambahkan kode yang membacanya (sebelum menulis ke sana) tidak akan dikompilasi lagi.
CodesInChaos
1
Benar, poin bagus, Anda akan mendapatkan kesalahan jika Anda menggunakan variabel yang tidak diinisialisasi, sehingga nilainya tidak dapat digunakan.
JohnD
1
dipilih karena baris "Guid = Guid.NewGuid ();" dapat membingungkan pengembang yang lebih baru. Pertimbangkan untuk mengedit sesuatu seperti "Guid someGuid = Guid.NewGuid ();" seperti garis g2;)
daviesdoesit
25

Coba lakukan:

Guid foo = Guid.NewGuid();
Dylan Smith
sumber
1
Alasan downvote: "Guid" adalah tipe tetapi digunakan seperti variabel.
daviesdoesit
19

Tidak dapat memberi tahu Anda berapa kali ini tertangkap. saya.

Guid myGuid = Guid.NewGuid(); 
Matt Dawdy
sumber
11

Dengan semangat lengkap, jawaban yang menginstruksikan Anda untuk digunakan Guid.NewGuid()adalah benar.

Dalam menangani pengeditan berikutnya, Anda harus memposting kode untuk RequestObjectkelas Anda . Saya curiga bahwa properti pemandu Anda tidak ditandai sebagai DataMember, dan karenanya tidak disambungkan melalui kawat. Karena default(Guid)sama dengan new Guid()(yaitu semuanya 0), ini akan menjelaskan perilaku yang Anda lihat.

Adam Robinson
sumber