หากรหัสแฮชของ null เป็นศูนย์เสมอใน. NET


88

เนื่องจากคอลเลกชันเช่นSystem.Collections.Generic.HashSet<>ยอมรับnullเป็นสมาชิกชุดหนึ่งสามารถถามว่ารหัสแฮชnullควรเป็นอย่างไร ดูเหมือนว่ากรอบจะใช้0:

// nullable struct type
int? i = null;
i.GetHashCode();  // gives 0
EqualityComparer<int?>.Default.GetHashCode(i);  // gives 0

// class type
CultureInfo c = null;
EqualityComparer<CultureInfo>.Default.GetHashCode(c);  // gives 0

สิ่งนี้อาจเป็นปัญหา (เล็กน้อย) กับ enums ที่เป็นโมฆะ ถ้าเรากำหนด

enum Season
{
  Spring,
  Summer,
  Autumn,
  Winter,
}

จากนั้นNullable<Season>(เรียกอีกอย่างว่าSeason?) สามารถรับค่าได้เพียงห้าค่า แต่สองค่าคือnullและSeason.Springมีรหัสแฮชเหมือนกัน

เป็นเรื่องน่าดึงดูดที่จะเขียนตัวเปรียบเทียบความเท่าเทียมที่ "ดีกว่า" ดังนี้:

class NewNullEnumEqComp<T> : EqualityComparer<T?> where T : struct
{
  public override bool Equals(T? x, T? y)
  {
    return Default.Equals(x, y);
  }
  public override int GetHashCode(T? x)
  {
    return x.HasValue ? Default.GetHashCode(x) : -1;
  }
}

แต่มีเหตุผลใดบ้างที่nullควรเป็นรหัสแฮช0?

แก้ไข / เพิ่มเติม:

Object.GetHashCode()บางคนดูเหมือนจะคิดว่านี่เป็นเรื่องเกี่ยวกับการเอาชนะ มันไม่ได้เป็นจริง (ผู้เขียนของ .NET ก็ทำให้การแทนที่ของGetHashCode()ในNullable<>struct ซึ่งเป็นที่เกี่ยวข้องแม้ว่า.) การดำเนินการใช้งานเป็นลายลักษณ์อักษรจาก parameterless ไม่สามารถจัดการกับสถานการณ์ที่วัตถุที่มีรหัสกัญชาเราแสวงหาก็คือGetHashCode()null

นี้เป็นเรื่องเกี่ยวกับการดำเนินการตามวิธีนามธรรมหรือมิฉะนั้นการใช้วิธีการอินเตอร์เฟซEqualityComparer<T>.GetHashCode(T) IEqualityComparer<T>.GetHashCode(T)ตอนนี้ขณะที่การสร้างการเชื่อมโยงเหล่านี้เพื่อ MSDN ผมเห็นว่ามันบอกว่ามีที่วิธีการเหล่านี้โยนArgumentNullExceptionถ้าอาร์กิวเมนต์ nullแต่เพียงผู้เดียวของพวกเขาคือ นี่ต้องเป็นความผิดพลาดของ MSDN อย่างแน่นอน? การใช้งานของ. NET ไม่มีข้อยกเว้น การขว้างปาในกรณีนั้นจะทำลายความพยายามใด ๆ ที่จะเพิ่มลงnullในไฟล์HashSet<>. เว้นแต่HashSet<>จะมีบางสิ่งที่พิเศษเมื่อจัดการกับnullไอเท็ม (ฉันจะต้องทดสอบสิ่งนั้น)

แก้ไขใหม่ / เพิ่มเติม:

ตอนนี้ฉันพยายามดีบัก ด้วยHashSet<>ฉันสามารถยืนยันได้ว่าด้วยตัวเปรียบเทียบความเท่าเทียมเริ่มต้นค่าSeason.Springและnull จะสิ้นสุดในที่เก็บข้อมูลเดียวกัน นี้จะถูกกำหนดโดยอย่างระมัดระวังตรวจสอบสมาชิกของอาร์เรย์ส่วนตัวและm_buckets m_slotsโปรดทราบว่าดัชนีมักจะหักล้างกันโดยการออกแบบ

อย่างไรก็ตามรหัสที่ฉันให้ไว้ข้างต้นไม่สามารถแก้ไขปัญหานี้ได้ ปรากฎว่าHashSet<>จะไม่ถามตัวเปรียบเทียบความเท่าเทียมกันด้วยซ้ำว่าค่าเป็นnullอย่างไร นี่มาจากซอร์สโค้ดของHashSet<>:

    // Workaround Comparers that throw ArgumentNullException for GetHashCode(null).
    private int InternalGetHashCode(T item) {
        if (item == null) { 
            return 0;
        } 
        return m_comparer.GetHashCode(item) & Lower31BitMask; 
    }

ซึ่งหมายความว่าอย่างน้อยHashSet<>ก็เป็นไปไม่ได้ที่จะเปลี่ยนแฮชของnull. วิธีแก้ปัญหาคือเปลี่ยนแฮชของค่าอื่น ๆ ทั้งหมดดังนี้:

class NewerNullEnumEqComp<T> : EqualityComparer<T?> where T : struct
{
  public override bool Equals(T? x, T? y)
  {
    return Default.Equals(x, y);
  }
  public override int GetHashCode(T? x)
  {
    return x.HasValue ? 1 + Default.GetHashCode(x) : /* not seen by HashSet: */ 0;
  }
}

26
เหตุใดรหัสแฮชสำหรับ null จึงไม่ควรเป็นศูนย์ การชนกันของแฮชไม่ใช่จุดจบของโลกคุณก็รู้
Hot Licks

3
ยกเว้นว่ามันเป็นเรื่องที่รู้จักกันดีและเป็นเรื่องธรรมดาการชนกัน ไม่ใช่ว่ามันแย่หรือแม้แต่ปัญหาที่สำคัญ แต่ก็สามารถหลีกเลี่ยงได้อย่างง่ายดาย
Chris Pfohl

8
ฮ่า ๆ ทำไมฉันถึงคิดว่า "ถ้าเฟรมเวิร์ก. NET กระโดดลงจากสะพานคุณจะทำตามไหม" ...
Adam Houldsworth

3
ด้วยความอยากรู้อยากเห็นฤดูกาลว่างจะเป็นอย่างไร
SwDevMan81

1
โดยส่วนตัวแล้วนี่คือเหตุผลที่ฉันมักจะให้ค่า enums ของฉันเป็น "Empty" หรือ "Unknown" เป็นค่าแรกเสมอ ด้วยวิธีนี้ Season enum ของฉันจะไม่แสดงถึงฤดูใบไม้ผลิโดยที่ฉันตั้งค่าอย่างชัดเจนจึงทำให้ปัญหาเป็นโมฆะ
คริส

คำตอบ:


25

ตราบเท่าที่รหัสแฮชที่ส่งคืนสำหรับค่าว่างนั้นสอดคล้องกันกับประเภทคุณก็น่าจะใช้ได้ ข้อกำหนดเดียวสำหรับรหัสแฮชคือวัตถุสองชิ้นที่ถือว่าเท่ากันใช้รหัสแฮชเดียวกันร่วมกัน

การคืนค่า 0 หรือ -1 สำหรับค่า null ตราบใดที่คุณเลือกหนึ่งรายการและส่งคืนตลอดเวลาจะใช้ได้ เห็นได้ชัดว่ารหัสแฮชที่ไม่เป็นค่าว่างไม่ควรส่งคืนค่าใด ๆ ที่คุณใช้เป็นค่าว่าง

คำถามที่คล้ายกัน:

GetHashCode ในช่องว่าง?

GetHashCode ควรส่งคืนอะไรเมื่อตัวระบุของวัตถุเป็นโมฆะ

"หมายเหตุ" ของรายการ MSDNนี้จะกล่าวถึงรายละเอียดเพิ่มเติมเกี่ยวกับรหัสแฮช ปวดร้าวเอกสารไม่ได้ให้ความคุ้มครองหรือการอภิปรายของค่า null ใด ๆที่ทุกคน - ไม่ได้ในเนื้อหาของชุมชน

ในการแก้ไขปัญหาของคุณเกี่ยวกับ enum ให้ติดตั้งโค้ดแฮชใหม่เพื่อส่งคืนค่าที่ไม่ใช่ศูนย์เพิ่มรายการ enum "ไม่รู้จัก" ที่เป็นค่าเริ่มต้นเทียบเท่ากับ null หรืออย่าใช้ enums ที่เป็นโมฆะ

หาที่น่าสนใจโดยวิธีการ

ปัญหาอีกประการหนึ่งที่ฉันเห็นโดยทั่วไปคือรหัสแฮชไม่สามารถแสดงประเภท 4 ไบต์หรือใหญ่กว่าที่เป็นโมฆะได้โดยไม่มีการชนกันอย่างน้อยหนึ่งครั้ง (มากกว่าเมื่อขนาดประเภทเพิ่มขึ้น) ตัวอย่างเช่นรหัสแฮชของ int เป็นเพียง int ดังนั้นจึงใช้ช่วง int แบบเต็ม คุณเลือกค่าใดในช่วงนั้นเป็นค่าว่าง สิ่งที่คุณเลือกจะชนกับรหัสแฮชของค่านั้นเอง

การชนกันเองไม่จำเป็นต้องเป็นปัญหา แต่คุณต้องรู้ว่ามันอยู่ที่นั่น รหัสแฮชใช้ในบางสถานการณ์เท่านั้น ตามที่ระบุไว้ในเอกสารบน MSDN ไม่รับประกันว่ารหัสแฮชจะส่งคืนค่าที่แตกต่างกันสำหรับวัตถุที่แตกต่างกันดังนั้นจึงไม่ควรคาดหวัง


ฉันไม่คิดว่าคำถามที่คุณเชื่อมโยงจะคล้ายกันทั้งหมด เมื่อคุณเอาชนะObject.GetHashCode()ในชั้นเรียนของคุณเอง (หรือ struct), คุณรู้ว่ารหัสนี้จะได้รับการตีเมื่อคนจริงมีตัวอย่างของการเรียนของคุณ nullอินสแตนซ์ที่ไม่สามารถ นั่นเป็นเหตุผลที่คุณไม่เริ่มลบล้างObject.GetHashCode()ด้วยif (this == null) return -1;มีความแตกต่างระหว่าง "เป็นเรื่องnull" และ "เป็นวัตถุที่มีบางสาขาที่มีnull"
Jeppe Stig Nielsen

คุณพูดว่า: แน่นอนว่ารหัสแฮชที่ไม่ใช่ค่าว่างไม่ควรส่งคืนค่าใดก็ตามที่คุณใช้เป็นค่าว่าง ฉันเห็นด้วย และนั่นคือเหตุผลที่ว่าทำไมผมถามคำถามของฉันในสถานที่แรกเพราะเมื่อใดก็ตามที่เราเขียน Enum ที่Tแล้ว(T?)nullและ(T?)default(T)จะมีรหัสกัญชาเดียวกัน (ในการดำเนินงานในปัจจุบันของ .NET) ที่สามารถเปลี่ยนแปลงได้หากผู้ใช้งานของ. NET เปลี่ยนรหัสแฮชของnull หรืออัลกอริทึมรหัสแฮชของSystem.Enum.
Jeppe Stig Nielsen

ฉันยอมรับว่าลิงก์นั้นมีไว้สำหรับฟิลด์ภายในที่ว่างเปล่า คุณพูดถึงมันสำหรับ IEqualityComparer <T> ในการใช้งานของคุณรหัสแฮชยังคงเป็นประเภทเฉพาะดังนั้นคุณจึงยังคงอยู่ในสถานการณ์เดียวกันความสอดคล้องของประเภท การส่งคืนรหัสแฮชเดียวกันสำหรับ null ประเภทใด ๆ จะไม่สำคัญเนื่องจาก null ไม่มีประเภท
Adam Houldsworth

1
หมายเหตุ: ฉันอัปเดตคำถามของฉันสองครั้ง ปรากฎว่า (อย่างน้อยด้วยHashSet<> ) ไม่สามารถเปลี่ยนรหัสแฮชของnull.
Jeppe Stig Nielsen

6

โปรดจำไว้ว่ารหัสแฮชถูกใช้เป็นขั้นตอนแรกในการกำหนดความเท่าเทียมกันเท่านั้นและ [is / should] never (be) ใช้เป็นการกำหนดโดยพฤตินัยว่าวัตถุสองชิ้นเท่ากันหรือไม่

หากรหัสแฮชของออบเจ็กต์สองตัวไม่เท่ากันก็จะถือว่าไม่เท่ากัน (เพราะเราถือว่าการใช้งานที่ไม่เกี่ยวข้องนั้นถูกต้อง - กล่าวคือเราจะไม่เดาอีกครั้ง) หากมีรหัสแฮชเดียวกันก็ควรตรวจสอบความเท่าเทียมกันจริงซึ่งในกรณีnullของคุณค่า enum จะล้มเหลว

ด้วยเหตุนี้ - การใช้ศูนย์จะดีเท่ากับค่าอื่น ๆ ในกรณีทั่วไป

แน่นอนว่าจะมีสถานการณ์เช่น enum ของคุณซึ่งศูนย์นี้จะแชร์กับรหัสแฮชของค่าจริง คำถามคือสำหรับคุณค่าใช้จ่ายเล็กน้อยของการเปรียบเทียบเพิ่มเติมทำให้เกิดปัญหาหรือไม่

ถ้าเป็นเช่นนั้นให้กำหนดตัวเปรียบเทียบของคุณเองสำหรับกรณีที่เป็นโมฆะสำหรับประเภทเฉพาะของคุณและตรวจสอบให้แน่ใจว่าค่าว่างจะให้รหัสแฮชที่เหมือนกันเสมอ (แน่นอน!) และค่าที่ไม่สามารถให้ผลได้ อัลกอริทึมรหัสแฮชของตัวเอง สำหรับประเภทของคุณเองสิ่งนี้ทำได้ สำหรับคนอื่น ๆ - โชคดี :)


5

ไม่จำเป็นต้องเป็นศูนย์ - คุณสามารถทำได้ 42 ถ้าคุณต้องการ

สิ่งที่สำคัญคือความสม่ำเสมอในระหว่างการทำงานของโปรแกรม

มันเป็นเพียงการแสดงที่ชัดเจนที่สุดเพราะnullมักจะแสดงเป็นศูนย์ภายใน ซึ่งหมายความว่าในขณะที่ดีบักหากคุณเห็นรหัสแฮชเป็นศูนย์ระบบอาจแจ้งให้คุณคิดว่า "อืม .. นี่เป็นปัญหาการอ้างอิงที่เป็นโมฆะหรือไม่"

โปรดทราบว่าหากคุณใช้ตัวเลขเช่น0xDEADBEEFนั้นจะมีคนบอกได้ว่าคุณกำลังใช้เลขวิเศษ ... และคุณก็จะเป็นเช่นนั้น (คุณสามารถพูดได้ว่าศูนย์เป็นเลขวิเศษเช่นกันและคุณก็คิดถูก ... ยกเว้นว่าจะใช้กันอย่างแพร่หลายจนเป็นข้อยกเว้นของกฎ)


4

คำถามที่ดี.

ฉันเพิ่งลองเขียนโค้ดนี้:

enum Season
{
  Spring,
  Summer,
  Autumn,
  Winter,
}

และดำเนินการดังนี้:

Season? v = null;
Console.WriteLine(v);

มันกลับมา null

ถ้าฉันทำแทนปกติ

Season? v = Season.Spring;
Console.WriteLine((int)v);

มันจะกลับมา0ตามที่คาดไว้หรือSpringง่ายๆถ้าเราหลีกเลี่ยงการแคสต์ไปintถ้าเราหลีกเลี่ยงที่จะหล่อ

ดังนั้น .. หากคุณทำสิ่งต่อไปนี้:

Season? v = Season.Spring;  
Season? vnull = null;   
if(vnull == v) // never TRUE

แก้ไข

จากMSDN

หากวัตถุสองชิ้นเปรียบเทียบว่าเท่ากันเมธอด GetHashCode สำหรับแต่ละวัตถุจะต้องส่งคืนค่าเดียวกัน อย่างไรก็ตามหากวัตถุสองชิ้นไม่เปรียบเทียบเท่ากันเมธอด GetHashCode สำหรับวัตถุทั้งสองจะไม่ต้องส่งคืนค่าที่ต่างกัน

กล่าวอีกนัยหนึ่ง: ถ้าวัตถุสองชิ้นมีรหัสแฮชเดียวกันซึ่งไม่ได้หมายความว่าพวกมันเท่ากันให้ กำหนดความเท่าเทียมกันที่แท้จริง Equalsเท่ากับ

จาก MSDN อีกครั้ง:

เมธอด GetHashCode สำหรับอ็อบเจ็กต์ต้องส่งคืนโค้ดแฮชเดียวกันอย่างสม่ำเสมอตราบเท่าที่ไม่มีการปรับเปลี่ยนสถานะอ็อบเจ็กต์ที่กำหนดค่าส่งคืนของเมธอด Equals ของอ็อบเจ็กต์ โปรดทราบว่านี่เป็นจริงสำหรับการเรียกใช้งานแอปพลิเคชันในปัจจุบันเท่านั้นและสามารถส่งคืนรหัสแฮชอื่นได้หากแอปพลิเคชันถูกเรียกใช้อีกครั้ง


6
การชนกันตามความหมายหมายถึงวัตถุสองชิ้นที่ไม่เท่ากันมีรหัสแฮชเหมือนกัน คุณได้แสดงให้เห็นว่าวัตถุไม่เท่ากัน ตอนนี้พวกเขามีรหัสแฮชเหมือนกันหรือไม่? ตาม OP ที่พวกเขาทำหมายความว่านี่คือการชนกัน ตอนนี้มันไม่ใช่จุดจบของโลกที่จะเกิดการชนกันมันเป็นเพียงการชนกันที่มีโอกาสมากกว่าการแฮชเป็นโมฆะกับสิ่งอื่นที่ไม่ใช่ 0 ซึ่งส่งผลเสียต่อประสิทธิภาพ
Servy

1
แล้วคำตอบของคุณพูดว่าอะไร? คุณบอกว่า Season.Spring ไม่เท่ากับ null นั่นไม่ผิด แต่ตอนนี้มันยังไม่ตอบคำถาม แต่อย่างใด
Servy

2
@Servy: คำถามบอกว่าทำไมฉันถึงมีhascode เหมือนกันสำหรับ 2 object ที่แตกต่างกัน ( nullและSpring ) ดังนั้นคำตอบก็คือไม่มีการชนกันทำให้แม้จะมีรหัสแฮชเหมือนกัน แต่ก็ไม่เท่ากัน
Tigran

3
"คำตอบ: ทำไมไม่?" โอพีตอบคำถามของคุณล่วงหน้าว่า "ทำไมไม่" มีแนวโน้มที่จะทำให้เกิดการชนกันมากกว่าตัวเลขอื่น เขาสงสัยว่ามีเหตุผลที่เลือก 0 หรือไม่และยังไม่มีใครตอบได้
Servy

1
คำตอบนี้ไม่มีอะไรที่ OP ยังไม่รู้ซึ่งเห็นได้จากวิธีการถามคำถาม
Konrad Rudolph

4

แต่มีเหตุผลใดที่รหัสแฮชของ null ควรเป็น 0?

มันอาจเป็นอะไรก็ได้ ฉันมักจะเห็นด้วยว่า 0 ไม่จำเป็นต้องเป็นตัวเลือกที่ดีที่สุด แต่เป็นสิ่งที่อาจนำไปสู่ข้อบกพร่องน้อยที่สุด

ฟังก์ชันแฮชต้องส่งคืนแฮชเดียวกันสำหรับค่าเดียวกัน เมื่อมีอยู่องค์ประกอบที่ไม่นี้นี้เป็นจริงค่าที่ถูกต้องสำหรับกัญชาของ ถ้ามีค่าคงที่สำหรับสิ่งนี้เช่นอืมคนที่ใช้ค่านี้จะต้องรู้จักใช้ค่านั้น ถ้าพวกเขาไม่คิดถึงมันโอกาสที่พวกเขาจะใช้ 0 นั้นสูงกว่าค่าอื่น ๆ เล็กน้อยฉันคิดว่าnullobject.HashOfNullIEqualityComparer

อย่างน้อยสำหรับ HashSet <> มันเป็นไปไม่ได้ที่จะเปลี่ยนแฮชของ null

ดังที่ได้กล่าวไว้ข้างต้นฉันคิดว่ามันเป็นไปไม่ได้เลยที่จะหยุดเต็มรูปแบบเพียงเพราะมีอยู่หลายประเภทซึ่งเป็นไปตามแบบแผนที่แฮชของ null เป็น 0 อยู่แล้ว


เมื่อหนึ่งในการดำเนินการวิธีการEqualityComparer<T>.GetHashCode(T)สำหรับประเภทโดยเฉพาะอย่างยิ่งบางอย่างTที่ช่วยให้nullหนึ่งมีการทำบางสิ่งบางอย่างnullเมื่ออาร์กิวเมนต์เป็น คุณสามารถ (1) โยนArgumentNullException(2) ส่งคืน0หรือ (3) ส่งคืนอย่างอื่น ฉันรับคำตอบของคุณสำหรับคำแนะนำเสมอที่จะกลับมา0ในสถานการณ์นั้น?
Jeppe Stig Nielsen

@JeppeStigNielsen ฉันไม่แน่ใจเกี่ยวกับการโยนและการส่งคืน แต่ถ้าคุณเลือกที่จะกลับมาก็เป็นศูนย์แน่นอน
Roman Starkov

2

มันคือ 0 เพื่อความเรียบง่าย ไม่มีข้อกำหนดที่ยากเช่นนี้ คุณจะต้องตรวจสอบข้อกำหนดทั่วไปของการเข้ารหัสแฮชเท่านั้น

ตัวอย่างเช่นคุณต้องตรวจสอบให้แน่ใจว่าหากวัตถุสองชิ้นเท่ากันแฮชโค้ดของพวกเขาจะต้องเท่ากันด้วย ดังนั้นรหัสแฮชที่แตกต่างกันจะต้องเป็นตัวแทนของวัตถุที่แตกต่างกันเสมอ (แต่ไม่จำเป็นต้องเป็นจริงในทางกลับกัน: วัตถุที่แตกต่างกันสองชิ้นอาจมีรหัสแฮชเหมือนกันแม้ว่าสิ่งนี้จะเกิดขึ้นบ่อยครั้งแสดงว่านี่ไม่ใช่ฟังก์ชันแฮชที่มีคุณภาพดี แต่ก็ไม่มี ความต้านทานการชนที่ดี)

แน่นอนฉัน จำกัด คำตอบของฉันไว้ที่ข้อกำหนดของธรรมชาติทางคณิตศาสตร์ มี .NET เฉพาะเงื่อนไขทางเทคนิคเช่นกันซึ่งคุณสามารถอ่านได้ที่นี่ 0 สำหรับค่า null ไม่อยู่ในหมู่พวกเขา


1

ดังนั้นจึงสามารถหลีกเลี่ยงได้โดยใช้Unknownค่า enum (แม้ว่าจะดูแปลกไปหน่อยที่ a Seasonจะไม่รู้จัก) ดังนั้นสิ่งนี้จะลบล้างปัญหานี้:

public enum Season
{
   Unknown = 0,
   Spring,
   Summer,
   Autumn,
   Winter
}

Season some_season = Season.Unknown;
int code = some_season.GetHashCode(); // 0
some_season = Season.Autumn;
code = some_season.GetHashCode(); // 3

จากนั้นคุณจะมีค่ารหัสแฮชที่ไม่ซ้ำกันสำหรับแต่ละฤดูกาล


1
ใช่ แต่นี่ไม่ได้หมายความว่าคำถามจริงๆด้วยวิธีนี้ตามคำถามว่างจะชนกับ Uknown Differnce คืออะไร?
Tigran

@Tigran - เวอร์ชันนี้ไม่ใช้ประเภท nullable
SwDevMan81

ฉันเห็น แต่คำถามเกี่ยวกับประเภทว่างเปล่า
Tigran

ฉันมีฉากเป็นล้าน ๆ ครั้งใน SO ที่ผู้คนเสนอแนะเพื่อการปรับปรุงเป็นคำตอบ
SwDevMan81

1

โดยส่วนตัวแล้วฉันพบว่าการใช้ค่าที่เป็นโมฆะค่อนข้างอึดอัดและพยายามหลีกเลี่ยงเมื่อใดก็ตามที่ทำได้ ปัญหาของคุณเป็นเพียงเหตุผลอื่น บางครั้งมันก็มีประโยชน์มาก แต่กฎง่ายๆของฉันคือไม่ผสมประเภทค่ากับโมฆะถ้าเป็นไปได้เพียงเพราะสิ่งเหล่านี้มาจากสองโลกที่แตกต่างกัน ในกรอบงาน. NET พวกเขาดูเหมือนจะทำเช่นเดียวกัน - ประเภทค่าจำนวนมากมีTryParseวิธีการซึ่งเป็นวิธีการแยกค่าจากไม่มีค่า (null )

ในกรณีเฉพาะของคุณมันง่ายที่จะกำจัดปัญหาเพราะคุณจัดการกับSeasonประเภทของคุณเอง

(Season?)nullสำหรับฉันหมายถึง 'ไม่ได้ระบุซีซัน' เหมือนกับเมื่อคุณมีเว็บฟอร์มที่ไม่จำเป็นต้องมีบางช่อง ในความคิดของฉันมันจะดีกว่าที่จะระบุได้ว่าพิเศษ 'ค่า' ในenumตัวเองมากกว่าการใช้งาน Nullable<T>clunky มันจะเร็วกว่า (ไม่มีหมวย) อ่านง่ายขึ้น ( Season.NotSpecifiedvs null) และจะแก้ปัญหาของคุณด้วยรหัสแฮช

แน่นอนว่าสำหรับประเภทอื่น ๆ เช่นintคุณไม่สามารถขยายโดเมนค่าและกำหนดค่าหนึ่งในค่าพิเศษได้ แต่ด้วยint?การชนกันของรหัสแฮชเป็นปัญหาที่เล็กกว่ามากหากเป็นเช่นนั้น


เมื่อคุณพูดว่า "มวย" ฉันคิดว่าคุณหมายถึง "การตัด" คือการใส่ค่าโครงสร้างภายในโครงสร้างNullable<>(โดยที่HasValueสมาชิกจะถูกตั้งค่าเป็นtrue) แน่ใจหรือว่าปัญหาเล็กลงด้วยint?? หลายครั้งที่เราใช้ค่าเพียงไม่กี่ค่าintแล้วก็เทียบเท่ากับ enum (ซึ่งในทางทฤษฎีสามารถมีสมาชิกได้หลายคน)
Jeppe Stig Nielsen

โดยทั่วไปฉันจะบอกว่า enum ถูกเลือกเมื่อมีค่าที่ทราบจำนวน จำกัด ที่ต้องการ (2-10) ถ้าขีด จำกัด ใหญ่กว่าหรือไม่มีเลยก็intสมเหตุสมผลกว่า ความชอบแตกต่างกันไปแน่นอน
Maciej

0
Tuple.Create( (object) null! ).GetHashCode() // 0
Tuple.Create( 0 ).GetHashCode() // 0
Tuple.Create( 1 ).GetHashCode() // 1
Tuple.Create( 2 ).GetHashCode() // 2

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