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


189

Có một nghịch lý trong mô tả ngoại lệ: Đối tượng Nullable phải có giá trị (?!)

Đây là vấn đề:

Tôi có một DateTimeExtendedlớp học

{
  DateTime? MyDataTime;
  int? otherdata;

}

và một nhà xây dựng

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 InvalidOperationExceptionthông điệp:

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

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

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

Lưu ý oldDTElà không null. Tôi đã xóa Valuetừ myNewDT.MyDateTimenhưng ngoại lệ tương tự được đưa ra do một setter được tạo.


Các nhà xây dựng khác là gì?
Paul Creasey

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

Các constructor lấy một thể hiện của chính nó. Làm thế nào bạn tạo phiên bản đầu tiên đó?
Paul Creasey

nó được xây dựng dưới dạng new () không có tham số, và sau đó tôi thêm các giá trị (nó hoạt động).
Dani

6
Vấn đề đã được giải quyết - vấn đề không nằm ở đó ... đã có một setter được tạo ra cho otherdata và MyDateTime, đó là kiểm tra giá trị trước khi cài đặt nó .. bay khi nó null !!!
Dani

Câu trả lời:


201

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

Ngoại lệ mà bạn nhận được đã bị ném vào .Valuetài sản của Nullable DateTime , vì bắt buộc phải trả lại DateTime(vì đó là hợp đồng cho .Valuecác tiểu bang), nhưng nó không thể làm như vậy vì không có DateTimetrả lại, vì vậy nó ném ngoại lệ.

Nói chung, sẽ là một ý tưởng tồi khi gọi một cách mù quáng .Valuevề một loại không thể, 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ị (tức là thông qua .HasValuekiểm tra).

BIÊN TẬP

Đây là mã cho DateTimeExtendedđiều đó không ném 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ử nó như thế này:

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

Thêm .Valuevào other.MyDateTimegây ra một ngoại lệ. Loại bỏ nó được loại bỏ ngoại lệ. Tôi nghĩ rằng bạn đang nhìn sai chỗ.


Bạn đã đúng về .value, nhưng một cái gì đó khác gây ra ngoại lệ. Tôi đã xóa .value và tôi đã thay đổi thứ tự mã của hàm tạo - sao chép giá trị int trước, nhưng ngoại lệ tương tự được đưa ra.
Dani

Tôi đã nhận xét về câu hỏi - tìm thấy vấn đề, nó nằm trong một setter được tạo cho các thuộc tính.
Dani

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

Câu trả lời chính xác. Nhận được một ngoại lệ gọi .Valuemột đối tượng null có ý nghĩa (tôi đoán), nhưng thông báo ngoại lệ thực sự gây hiểu lầm nếu bạn tình cờ xử lý hai đối tượng Nullable. Một cái gì đó như 'Thuộc tính .Value yêu cầu đối tượng không phải là null' sẽ có ý nghĩa hơn nhiều.
DVK

9

Khi sử dụng phương pháp khuyến nông LINQ (ví dụ Select, Where), hàm lambda có thể được chuyển đổi sang SQL có thể không cư xử giống hệt với mã C #. Chẳng hạn, mạch ngắn của C # được đánh giá &&||được chuyển đổi thành háo hức 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.

Thí dụ:

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

5
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ó liên quan đến Ngoại lệ mà anh ấy 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.
Người bảo vệ một

6

Hãy thử thả .value

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

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

2

Trong trường hợp này oldDTE là null, vì vậy khi bạn cố gắng truy cập oldDTE. Giá trị của UnlimitedOperationException sẽ bị ném do không có giá trị. Trong ví dụ của bạn, bạn có thể chỉ cần làm:

this.MyDateTime = newDT.MyDateTime;

OldDTE không phải là null, nhưng dù sao tôi cũng đã xóa giá trị ... nó vẫn đang ném ngoại lệ đó ....
Dani

1

Chỉ định các thành viên trực tiếp mà không có .Valuephần:

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

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ó - thứ đã ném.


0

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

sName = myObj.Name;

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

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

Những công việc này.


1
Trước khi trả lời, vui lòng thử đọc qua các câu trả lời khác cho câu hỏi trước - đặc biệt là câu trả lời được chấp nhận nêu chính xác những gì bạn đặt trong câu trả lời của mình . Mặc dù nó không hiển thị nó bằng mã, nhưng nó đánh vần nó ra. 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;sName = myObj.Name;
mới
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.