2009-12-13 41 views
144

Có nghịch lý trong mô tả ngoại lệ: đối tượng Nullable phải có giá trịđối tượng nullable phải có giá trị

Đây là vấn đề (?!):

Tôi có một lớp DateTimeExtended, có

{ 
    DateTime? MyDataTime; 
    int? otherdata; 

} 

và một constructor

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

chạy mã này

DateTimeExtended res = new DateTimeExtended(oldDTE); 

ném một InvalidOperationException với thông điệp:

đối tượng Nullable phải có giá trị.

myNewDT.MyDateTime.Value - hợp lệ và chứa đối tượng DateTime thông thường.

Ý nghĩa của thông báo này là gì và tôi đang làm gì sai?

Lưu ý rằng oldDTE không phải là null. Tôi đã xóa Value khỏi myNewDT.MyDateTime nhưng ngoại lệ tương tự cũng được ném do bộ công cụ được tạo.

+0

các nhà xây dựng khác là gì? –

+0

Lạ. Tôi tái tạo ngoại lệ với .Value ở đó, và không có ngoại lệ mà không có .Value ở đó. Bạn có chắc là bạn đang chạy mã được cập nhật không? – Yuliy

+0

Hàm khởi tạo lấy một cá thể của chính nó. bạn tạo ra ví dụ đầu tiên như thế nào? –

Trả lời

147

Bạn nên thay đổi dòng this.MyDateTime = myNewDT.MyDateTime.Value; chỉ this.MyDateTime = myNewDT.MyDateTime;

Trường hợp ngoại lệ bạn đã nhận được ném vào .Value tài sản của NullableDateTime, vì nó được yêu cầu trả lại DateTime (vì đó là hợp đồng của các trạng thái .Value), nhưng không thể làm như vậy vì không có DateTime để trả lại, do đó, nó sẽ loại trừ một ngoại lệ.

Nói chung, đó là một ý tưởng tồi để mù quáng gọi .Value trên một loại nullable, trừ khi bạn có một số kiến ​​thức trước đó rằng biến PHẢI chứa một giá trị (ví dụ: thông qua một tấm séc .HasValue).

EDIT

Dưới đây là các mã cho DateTimeExtended mà không ném một ngoại lệ:

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

    public DateTimeExtended() { } 

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

Tôi đã thử nghiệm nó như thế này:

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

Thêm .Value trên other.MyDateTime gây ra ngoại lệ. Loại bỏ nó sẽ loại bỏ ngoại lệ. Tôi nghĩ rằng bạn đang tìm kiếm ở nơi sai.

+0

Bạn nói đúng về .value, nhưng cái gì khác gây ra ngoại lệ. Tôi đã loại bỏ các .value, và tôi đã thay đổi thứ tự mã của constructor-sao chép giá trị int đầu tiên, nhưng cùng một ngoại lệ được ném. – Dani

+0

Tôi đã nhận xét về câu hỏi - đã tìm thấy sự cố, nó nằm trong trình thiết lập được tạo cho các thuộc tính. – Dani

+0

có, nó giải quyết vấn đề của tôi, tôi chỉ cần thay đổi đối tượng có thể null để không null, và chuyển đổi datetime thành chuỗi trực tiếp, không phải bởi datetimeobject.value.datetime.tostring() – adnan

4

Hãy thử thả .Value

+0

không giúp ích gì. nó ném cùng một ngoại lệ nếu tôi chạy dòng thứ 2 trước. – Dani

1

Gán các thành viên trực tiếp mà không .Value phần:

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

Trong trường hợp này oldDTE là null, vì vậy khi bạn cố gắng truy cập vào các oldDTE.Value InvalidOperationException được ném từ không có giá trị. Trong ví dụ của bạn, bạn chỉ đơn giản có thể làm:

this.MyDateTime = newDT.MyDateTime; 
+0

Các oldDTE không phải là null, nhưng tôi loại bỏ các giá trị dù sao đi nữa ... nó vẫn còn ném ngoại lệ đó .... – Dani

0

Có vẻ như oldDTE.MyDateTime là null, vì vậy hàm tạo đã cố gắng lấy Giá trị của nó - đã ném.

0

Tôi nhận được thông báo này khi cố truy cập các giá trị của một đối tượng có giá trị rỗng.

sName = myObj.Name; 

điều này sẽ tạo ra lỗi. Trước tiên, bạn nên kiểm tra xem đối tượng có không rỗng không

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

Tác phẩm này hoạt động.

+0

Trước khi trả lời, trước tiên hãy thử đọc qua các câu trả lời khác cho câu hỏi - đặc biệt là câu trả lời được chấp nhận cho biết chính xác những gì bạn đã đặt trong câu trả lời * của bạn *. Mặc dù nó không hiển thị nó bằng cách sử dụng mã, nó đánh vần nó. Ngoài ra, hãy thử làm cho mã ví dụ của bạn có liên quan đến câu hỏi - chẳng hạn như 'this.MyDateTime = myNewDT.MyDateTime.Value;', không phải 'sName = myObj.Name;' – newfurniturey

2

Khi sử dụng phương pháp mở rộng LINQ (ví dụ: Select, Where), hàm lambda có thể được chuyển đổi thành SQL có thể không hoạt động giống với mã C# của bạn. Ví dụ, ngắn mạch của C# được đánh giá ||&& được chuyển đổi thành mong muốn của SQL ANDOR. Điều này có thể gây ra vấn đề khi bạn kiểm tra null trong lambda của bạn.

Ví dụ:

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

Tôi nhận ra câu trả lời này không liên quan đến trường hợp cụ thể của OP , nhưng nó có liên quan đến ngoại lệ anh ta nhận được. Ngoài ra, trang này là lần truy cập đầu tiên trên Google cho ngoại lệ đó, điều này làm cho nó có liên quan. –

Các vấn đề liên quan