ToString ที่ Nullable ()


142

ฉันเห็นสิ่งปลูกสร้างทุกแห่งเช่น:

int? myVar = null;
string test = myVar.HasValue ? myVar.Value.ToString() : string.Empty;

ทำไมไม่ใช้เพียง:

string test = myVar.ToString();

มันไม่เหมือนกันเหรอ? อย่างน้อย Reflector บอกว่า:

public override string ToString()
{
  if (!this.HasValue)
  {
    return "";
  }
  return this.value.ToString();
}

ดังนั้นนั่นถูกต้อง (เวอร์ชั่นที่สั้นกว่า) หรือฉันขาดอะไรไป?


1
ฉันไม่ได้เห็นรหัสเช่นนี้ :)
tymtam

คำตอบ:


112

คุณค่อนข้างถูกต้อง นอกจากนี้ในคำถามนี้เราขอแนะนำวิธีแก้ปัญหาแบบเดิมขณะที่ไม่มีใครสังเกตเห็นToString()คำตอบที่ถูกต้องอยู่แล้ว

บางทีอาร์กิวเมนต์สำหรับโซลูชัน verbose เพิ่มเติมคืออ่านได้: เมื่อคุณเรียกใช้ ToString()ในสิ่งที่ควรจะเป็นnullคุณจะคาดหวังNullReferenceExceptionแม้ว่านี่มันไม่ได้โยน


21
ที่จริงแล้วอย่างน้อยสองคนสังเกตเห็น: Eric Lippert และ Johannes Rössel
Jon Skeet

7
ในขณะที่ฉันแน่ใจว่าไม่ใช่สิ่งที่คุณหมายถึงการอ้างอิงไม่เป็นโมฆะที่นี่ Nullable <T> เป็นประเภทค่า นี่คือเหตุผลที่การโทรToString()ทำงานโดยไม่NullReferenceExceptionถูกโยนทิ้ง
Thorarin

2
หากนั่นคือความคิดคุณจะคาดหวังว่า.HasValueจะยังคงโยนข้อยกเว้นนั้น
Extragorey

อีกเหตุผลหนึ่งที่ผู้คนใช้เวอร์ชัน verbose อาจเป็นเพราะความเท่าเทียมกับนิพจน์เช่นmyNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nullที่คุณต้องการให้วัตถุที่ไม่ได้ห่อเพื่อเข้าถึงToStringวิธีที่ต้องการ แน่นอนว่ามีวิธีแก้ปัญหาที่กระชับกว่านี้เช่นกัน:$"{myNullableDateTime:d}"
Extragorey

14

ฉันคิดว่าหลายคนมีการตรวจสอบดังกล่าวเพราะมันไม่ใช่พฤติกรรมตามธรรมชาติของวัตถุที่สามารถเก็บค่าว่างได้


@Andrew เห็นด้วยเพราะคน (เช่นฉัน) คิดว่าในตอนแรกว่ามันจะมีข้อยกเว้น
นาธานคูป

1
ฉันไม่รู้ว่านี่เป็นพฤติกรรม แน่นอนฉันจะคิดว่าโครงสร้างใด ๆ ที่ส่งกลับค่าจริงสำหรับ (x == null) ก็จะโยน NullReferenceException ถ้าคุณเรียก x.ToString ()
Dan Bryant

5

ไม่คุณถูกต้องเวอร์ชั่นที่สั้นกว่าจะเหมือนกับที่คนอื่นทำในเรื่องนั้น สิ่งก่อสร้างอื่น ๆ ที่ฉันมักจะใช้บ่อยๆแทนที่จะเป็น ternary ที่มีค่า nullables ก็คือตัวดำเนินการรวมตัวเป็นศูนย์ ซึ่งยังช่วยปกป้องคุณจากโมฆะ สำหรับ ToString () ไม่จำเป็น (ตามที่คุณระบุ) แต่สำหรับค่า int เริ่มต้น (ตัวอย่าง) มันใช้งานได้ดีเช่น:

int page = currentPage ?? 1;

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


5

ฉันรู้มานานแล้วหลังจากนั้นมีความเกี่ยวข้อง แต่ ... ฉันสงสัยว่ามันเป็นเพราะประเภท nullable เช่น int? วิธีการ. ToString () ไม่อนุญาตให้คุณใช้สตริงรูปแบบ ดูฉันจะฟอร์แมต DateTime ที่ไม่มีค่าด้วย ToString () ได้อย่างไร . บางทีในรหัสต้นฉบับมีสตริงรูปแบบใน. ToString () หรือบางที coder ลืมว่า. ToString () โดยไม่มีสตริงรูปแบบยังคงมีอยู่ในประเภท nullable


3

อาจเป็นเพียงการทำตามรูปแบบ? หรือพวกเขาไม่รู้แบ็กเอนด์ คุณเป็นรหัสที่ถูกต้องเหมือนกันทุกประการ คุณสามารถทำได้:

int? i = null;
i.ToString(); //No NullReferenceException

คุณอาจต้องใช้เส้นทางยาวหาก ToString () จำเป็นต้องมีวัฒนธรรมที่ไม่เปลี่ยนแปลงเนื่องจากไม่มีค่าในเมนู
ΕГИІИО

1

int?คือน้ำตาลซินแทกซ์ซึ่งลดความซับซ้อนของการประกาศตัวแปร nullable มันเป็นเช่นเดียวกับNullable<int>มันเป็นเช่นเดียวกับ

ดังนั้นหากคุณดูที่การใช้ToString()วิธีการNullable<T> (ดูด้านล่าง)คุณสามารถสังเกตเห็นว่ามันส่งกลับสตริงที่ว่างเปล่าในกรณีที่มันไม่มีค่า

public struct Nullable<T> where T : struct
{
    public override string ToString()
    {
      if (!this.hasValue)
        return "";
      return this.value.ToString();
    }
}

สิ่งที่ MSDN พูดว่า:

Nullable.ToString วิธี

ส่งคืนการแทนข้อความของค่าของวัตถุ Nullable ปัจจุบันถ้าคุณสมบัติ HasValue เป็นจริงหรือสตริงว่างเปล่า ("") ถ้าคุณสมบัติ HasValue เป็นเท็จ

ดังนั้นรหัสต่อไปนี้จะพิมพ์สตริงที่ว่างเปล่าเพื่อคอนโซลแทนการโยนArgumentNullExceptionข้อยกเว้น

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.