Guid คือ 0 ทั้งหมด (ศูนย์)?


241

ฉันกำลังทดสอบบริการ WCF บางอย่างที่ส่งวัตถุด้วย Guids ไปมา ในรหัสทดสอบแอปบนเว็บของฉันฉันกำลังทำสิ่งต่อไปนี้:

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

ด้วยเหตุผลบางอย่างการเรียกใช้Guid ()ใหม่กำลังสร้าง Guids ด้วย 0 ทั้งหมด (ศูนย์) ดังนี้:

00000000-0000-0000-0000-000000000000

สิ่งใดที่ทำให้เกิดสิ่งนี้


9
หลังจากแก้ไขแล้วนี่เป็นคำถามใหม่ทั้งหมด และจำเป็นต้องมีข้อมูลมากขึ้นเพื่อกำหนดคำตอบใหม่
Scott Rippey

3
ลบส่วนที่แก้ไขซึ่งเปลี่ยนแปลงคำถาม
Didaxis

115
+1 เพราะผมเคยใช้คำถามนี้จะขโมยว่างเปล่า Guid โหลครั้ง :)
jmosesman

5
@jmosesman ดีกว่าที่จะใช้แบบฟอร์มGuid.Empty
Jonathan Moosekian

4
@ JonathanM ฉันใช้จริงในสคริปต์ SQL โพสต์นี้เพิ่งแสดงขึ้นก่อนหลังจากค้นหา
jmosesman

คำตอบ:


428

ใช้วิธีการแบบคงที่Guid.NewGuid()แทนการเรียกตัวสร้างเริ่มต้น

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

18
+1 สำหรับคำตอบที่ถูกต้องเช่นเดียวกับลิงก์ไปยังเอกสารที่ถูกต้อง
ObscureRobot

109

บทเรียนที่จะเรียนรู้จากสิ่งนี้:

1) Guid เป็นประเภทค่าไม่ใช่ประเภทอ้างอิง

2) การเรียกคอนสตรัคเตอร์เริ่มต้นnew S()ในประเภทค่าใด ๆ จะให้รูปแบบค่าศูนย์ทั้งหมดของรูปแบบนั้นไม่ว่าจะเป็นอะไรก็ตาม default(S)มันเป็นเหตุผลเดียวกับ


3
มันรวบรวมใน IL เดียวกันกับdefault(S)หรือมี subtleties ใด ๆ ที่ฉันหายไป?
กำหนดค่า

8
@ ผู้สร้าง: มันทำ ในความเป็นจริงการเป็นตัวแทนภายในของคอมไพเลอร์ของ "default (S)" และ "new S ()" เหมือนกัน เราไม่เห็นความแตกต่างภายในซึ่งได้นำไปสู่ข้อบกพร่องที่โชคร้ายบางกว่าปีที่ผ่านมาเพราะพวกเขาอยู่ในความเป็นจริงไม่ได้ค่อนข้างเหมือนกัน ตัวอย่างเช่นconst int x = new int();ไม่ควรถูกกฎหมายตามข้อกำหนด แต่const int x = default(int);เป็น; เราอนุญาตให้ทั้งสอง
Eric Lippert

1
@configurator - หากคุณสนใจกรณีมุมที่เกี่ยวข้องบางทีmsmvps.com/blogs/jon_skeet/archive/2008/12/10//ก็น่าสนใจเช่นกัน
kvb

56

ลองใช้สิ่งนี้แทน:

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

สิ่งนี้จะสร้างค่า Guid ที่ 'จริง' เมื่อคุณใหม่ประเภทการอ้างอิงมันจะให้ค่าเริ่มต้น (ซึ่งในกรณีนี้คือศูนย์ทั้งหมดสำหรับ Guid)

เมื่อคุณสร้าง Guid ใหม่มันจะเริ่มต้นให้เป็นศูนย์ทั้งหมดซึ่งเป็นค่าเริ่มต้นสำหรับ Guid โดยพื้นฐานแล้วจะเหมือนกับการสร้าง int "ใหม่" (ซึ่งเป็นประเภทค่า แต่คุณสามารถทำสิ่งนี้ได้):

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

เปรียบเทียบสิ่งนี้กับการทำสิ่งเดียวกันกับ int:

int i1;                     // i1 is 0
int i2 = new int();         // i2 is 0
int i3 = default(int);      // i3 is 0

1
g1จะรวบรวมเป็นฟิลด์เท่านั้นและไม่เป็นตัวแปรโลคัล นอกจากนี้ดัชนีในคอลัมน์ความคิดเห็นของคุณไม่ตรงกับบรรทัดเดียวกันของรหัส
CodesInChaos

1
@CodeInChaos: ขอบคุณแก้ไขความคิดเห็น FYI, บรรทัด g1 รวบรวมได้จริง ๆ ...
JohnD

3
มันจะรวบรวมตามที่เป็นอยู่ แต่ไม่มีค่าที่กำหนดไว้ หากคุณเพิ่มโค้ดที่อ่าน (ก่อนที่จะเขียน) มันจะไม่รวบรวมอีกต่อไป
CodesInChaos

1
ถูกต้องจุดดีคุณจะได้รับข้อผิดพลาดหากคุณใช้ตัวแปรที่ไม่กำหนดค่าเริ่มต้นดังนั้นจึงไม่สามารถใช้ค่าได้
JohnD

1
ลงคะแนนเนื่องจากบรรทัด "Guid = Guid.NewGuid ();" อาจสับสนนักพัฒนาใหม่ ลองแก้ไขเป็น "Guid someGuid = Guid.NewGuid ();" เช่นเดียวกับสาย g2;)
daviesdoesit



11

ในจิตวิญญาณของความสมบูรณ์คำตอบที่แนะนำให้คุณใช้Guid.NewGuid()นั้นถูกต้อง

ในการแก้ไขที่ตามมาคุณจะต้องโพสต์รหัสสำหรับRequestObjectชั้นเรียนของคุณ ฉันสงสัยว่าคุณสมบัติ guid ของคุณไม่ได้ถูกทำเครื่องหมายว่าเป็น a DataMemberและดังนั้นจึงไม่ได้รับการจัดอันดับผ่านสาย เนื่องจากdefault(Guid)เป็นเช่นเดียวกับnew Guid()(เช่นทุกคน0) สิ่งนี้จะอธิบายพฤติกรรมที่คุณเห็น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.