วัตถุที่ nullable ต้องมีค่า


190

มีบุคคลที่ผิดธรรมดาในคำอธิบายข้อยกเว้น: วัตถุที่ Nullable ต้องมีค่า (?!)

ปัญหานี้เป็นปัญหา:

ฉันมีDateTimeExtendedชั้นเรียนที่มี

{
  DateTime? MyDataTime;
  int? otherdata;

}

และผู้สร้าง

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime.Value;
   this.otherdata = myNewDT.otherdata;
}

ใช้รหัสนี้

DateTimeExtended res = new DateTimeExtended(oldDTE);

ขว้างInvalidOperationExceptionด้วยข้อความ:

วัตถุที่ Nullable ต้องมีค่า

myNewDT.MyDateTime.Value- ถูกต้องและมีDateTimeวัตถุปกติ

ข้อความนี้มีความหมายอะไรและฉันทำอะไรผิด

โปรดทราบว่าไม่oldDTE nullฉันได้ลบออกValueจากmyNewDT.MyDateTimeแต่ข้อยกเว้นเดียวกันถูกโยนเนื่องจาก setter ที่สร้างขึ้น


คอนสตรัคเตอร์อื่นคืออะไร?
Paul Creasey

แปลก. ฉันทำซ้ำข้อยกเว้นด้วย. มีค่าและไม่ได้รับการยกเว้นถ้าไม่มี. คุณแน่ใจหรือว่าคุณกำลังเรียกใช้รหัสที่อัปเดตอยู่
Yuliy

ตัวสร้างใช้อินสแตนซ์ของตัวเอง คุณสร้างอินสแตนซ์แรกนั้นได้อย่างไร
Paul Creasey

มันถูกสร้างเป็นใหม่ () โดยไม่มีพารามิเตอร์จากนั้นฉันเพิ่มค่า (ใช้งานได้)
Dani

6
แก้ไขปัญหา - ปัญหาไม่ได้อยู่ที่นั่น ... มี setter ที่สร้างขึ้นเพื่อ otherdata และ MyDateTime นั่นคือการตรวจสอบค่าก่อนที่จะตั้ง .. บินเมื่อมันเป็นโมฆะ !!!
Dani

คำตอบ:


201

คุณควรเปลี่ยนสายthis.MyDateTime = myNewDT.MyDateTime.Value;เป็นเพียงthis.MyDateTime = myNewDT.MyDateTime;

ข้อยกเว้นที่คุณได้รับนั้นถูกส่งไปใน.Valueทรัพย์สินของNullable DateTimeเนื่องจากจำเป็นต้องส่งคืน a DateTime(เนื่องจากเป็นสัญญาสำหรับ.Valueรัฐ) แต่ไม่สามารถทำได้เนื่องจากไม่มีDateTimeการส่งคืนดังนั้นจึงมีข้อยกเว้น

โดยทั่วไปเป็นความคิดที่ไม่ดีที่จะเรียก.Valueใช้ nullable แบบสุ่มสี่สุ่มห้าเว้นแต่ว่าคุณมีความรู้มาก่อนว่าตัวแปรนั้นต้องมีค่า (เช่นผ่านการ.HasValueตรวจสอบ)

แก้ไข

นี่คือรหัสสำหรับDateTimeExtendedสิ่งที่ไม่ทำให้เกิดข้อยกเว้น:

class DateTimeExtended
{
    public DateTime? MyDateTime;
    public int? otherdata;

    public DateTimeExtended() { }

    public DateTimeExtended(DateTimeExtended other)
    {
        this.MyDateTime = other.MyDateTime;
        this.otherdata = other.otherdata;
    }
}

ฉันทดสอบแบบนี้:

DateTimeExtended dt1 = new DateTimeExtended();
DateTimeExtended dt2 = new DateTimeExtended(dt1);

การเพิ่มการ.Valueเปิดother.MyDateTimeทำให้เกิดข้อยกเว้น การลบมันจะเป็นการกำจัดข้อยกเว้น ฉันคิดว่าคุณกำลังมองหาที่ที่ผิด


คุณถูกต้องเกี่ยวกับ. value แต่มีสิ่งอื่นที่ทำให้เกิดข้อยกเว้น ฉันได้ลบค่า. และฉันได้เปลี่ยนลำดับรหัสของตัวสร้าง - คัดลอกค่า int ก่อน แต่มีข้อยกเว้นเดียวกันถูกโยน
Dani

ฉันได้แสดงความคิดเห็นกับคำถาม - พบปัญหามันอยู่ใน setter ที่สร้างขึ้นสำหรับคุณสมบัติ
Dani

ใช่มันแก้ไขปัญหาของฉันฉันเพิ่งเปลี่ยนวัตถุที่สามารถ null เป็นไม่สามารถ null และแปลงวันที่และเวลาสตริงโดยตรงไม่ใช่โดย datetimeobject.value.datetime.tostring ()
adnan

คำตอบที่ดี การรับข้อยกเว้นในการเรียก.Valueใช้อ็อบเจกต์ null นั้นสมเหตุสมผล (ฉันเดา) แต่ข้อความข้อยกเว้นนั้นทำให้เข้าใจผิดได้จริง ๆ ถ้าคุณจัดการวัตถุ Nullable สองรายการ บางอย่างเช่น 'คุณสมบัติ. ค่าต้องใช้วัตถุที่จะไม่เป็นโมฆะ' จะทำให้รู้สึกมากขึ้นทั้งหมด
DVK

9

เมื่อใช้วิธีการขยาย LINQ (เช่นSelect, Where), ฟังก์ชั่นแลมบ์ดาอาจจะมีการแปลงเป็น SQL ที่อาจจะไม่ประพฤติตัวเหมือนกันกับรหัสของคุณ C # ยกตัวอย่างเช่น C # 's ลัดวงจรประเมิน&&และ||จะถูกแปลงเป็น SQL ของความกระตือรือร้นและAND ORสิ่งนี้อาจทำให้เกิดปัญหาเมื่อคุณตรวจสอบ null ในแลมบ์ดาของคุณ

ตัวอย่าง:

MyEnum? type = null;
Entities.Table.Where(a => type == null || 
    a.type == (int)type).ToArray();  // Exception: Nullable object must have a value

5
ฉันรู้ว่าคำตอบนี้ไม่เกี่ยวข้องกับกรณีเฉพาะของ OP แต่เกี่ยวข้องกับข้อยกเว้นที่เขาได้รับ นอกจากนี้หน้านี้เป็นที่นิยมอย่างมากใน Google สำหรับข้อยกเว้นนั้นซึ่งทำให้มีความเกี่ยวข้อง
ป้องกันหนึ่ง

6

ลองทำหล่น .value

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}

ไม่ช่วย มันจะโยนข้อยกเว้นเดียวกันถ้าฉันเรียกใช้บรรทัดที่ 2 ก่อน
Dani

2

ในกรณีนี้ oldDTE เป็นโมฆะดังนั้นเมื่อคุณพยายามที่จะเข้าถึง oldDTE มูลค่า InvalidOperationException จะถูกโยนทิ้งเนื่องจากไม่มีค่า ในตัวอย่างของคุณคุณสามารถทำได้:

this.MyDateTime = newDT.MyDateTime;

oldDTE ไม่ได้เป็นโมฆะ แต่ฉันออกค่า แต่อย่างใด ... มันก็ยังคงขว้างปายกเว้นว่า ....
Dani


0

ดูเหมือนว่า oldDTE.MyDateTime นั้นไม่มีค่าดังนั้นตัวสร้างจะพยายามใช้ค่าของมัน - ซึ่งทำให้เกิด


0

ฉันได้รับข้อความนี้เมื่อพยายามเข้าถึงค่าของวัตถุที่มีค่า Null

sName = myObj.Name;

สิ่งนี้จะทำให้เกิดข้อผิดพลาด ก่อนอื่นคุณควรตรวจสอบว่าวัตถุไม่เป็นโมฆะหรือไม่

if(myObj != null)
  sName = myObj.Name;

วิธีนี้ใช้ได้ผล


1
ก่อนที่จะตอบโปรดลองอ่านคำตอบอื่น ๆ สำหรับคำถามแรก - โดยเฉพาะอย่างยิ่งคำตอบที่ได้รับการยอมรับว่ารัฐว่าสิ่งที่คุณวางไว้ในของคุณคำตอบ แม้ว่ามันจะไม่แสดงโดยใช้รหัส แต่มันก็สะกดออกมา นอกจากนี้ยังพยายามที่จะทำให้โค้ดตัวอย่างที่เกี่ยวข้องกับคำถามของเช่น - this.MyDateTime = myNewDT.MyDateTime.Value;ไม่sName = myObj.Name;
newfurniturey

0

ฉันได้รับโซลูชั่นนี้และมันใช้งานได้สำหรับฉัน

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