2012-04-16 19 views
12

Tôi mong chờ ba dòng tiếp theo của mã để được như vậy:sử dụng coalescing điều hành null trên các loại nullable thay đổi ngầm loại

public static void TestVarCoalescing(DateTime? nullableDateTime) 
{ 
    var dateTimeNullable1 = nullableDateTime.HasValue ? nullableDateTime : DateTime.Now; 
    var dateTimeNullable2 = nullableDateTime != null ? nullableDateTime : DateTime.Now; 
    var dateTimeWhatType = nullableDateTime ?? DateTime.Now; 
} 

Trong mọi trường hợp, tôi gán nullableDateTime vào biến mới. Tôi hy vọng loại của tất cả các biến sẽ trở thành DateTime? vì đó là loại nullableDateTime. Nhưng với sự ngạc nhiên của tôi, loại dateTimeWhatType chỉ trở thành DateTime, vì vậy không thể vô hiệu. Để làm cho mọi việc tồi tệ hơn, ReSharper gợi ý thay thế câu lệnh thứ hai bằng một biểu thức kết hợp rỗng, biến nó thành biểu thức 3. Vì vậy, nếu tôi để ReSharper làm điều đó, kiểu biến sẽ thay đổi từ DateTime? thành DateTime.

Trong thực tế, chúng ta hãy nói rằng trong thời gian còn lại của phương pháp này, tôi sẽ sử dụng

if (someCondition) dateTimeNullable2 = null; 

Điều đó sẽ biên dịch tốt, cho đến khi tôi để cho ReSharper thay thế biểu thức thứ hai với phiên bản coalescing null.

AFAIK, thay thế

somevar != null ? somevar : somedefault; 

với

somevar ?? somedefault; 

thực sự nên tạo ra kết quả tương tự. Nhưng đối với việc gõ ngầm định trên một kiểu nullable, trình biên dịch dường như đe dọa ?? như thể nó có nghĩa là.

somevar != null ? somevar.Value : somedefault; 

Vì vậy, tôi đoán câu hỏi của tôi là lý do tại sao các loại ngầm được thay đổi khi tôi sử dụng ??, và cũng là nơi trong tài liệu tôi có thể tìm thông tin về vấn đề này.

BTW, đây không phải là một kịch bản thế giới thực, nhưng tôi muốn biết tại sao sử dụng ?? thay đổi loại (ẩn).

+3

Tại sao bạn mong đợi 'nullableDateTime ?? DateTime.Now' để tạo ra một 'DateTime? ', Khi trình biên dịch có đủ thông tin để biết rằng kết quả sẽ không bao giờ là' null'? –

+0

@Damien: trong ví dụ đầu tiên và thứ hai của tôi trình biên dịch cũng có đủ thông tin để biết kết quả sẽ không bao giờ là 'null'. Đó chính xác là lý do tại sao tôi thấy kiểu hành vi kỳ lạ này. – comecme

+1

Nhưng '?: 'hỗ trợ một phạm vi lớn hơn nhiều đầu vào có thể (không có lý do gì' điều kiện' cần được kết nối với một trong hai kết quả 'biểu hiện' ở tất cả). Như vậy, sẽ không bình thường khi trình biên dịch được kiến ​​trúc để thực hiện phân tích này chống lại '?:'. Trong khi đó, đối với '??', nó biết chính xác rằng kết quả sẽ là biểu thức đầu tiên mà không có khả năng biểu thức đó là null, hoặc biểu thức thứ hai. –

Trả lời

6

Hai ví dụ đầu tiên của bạn đang dẫn bạn lạc lối; tốt hơn là nên xem xét không

var dateTimeNullable1 = nullableDateTime.HasValue 
    ? nullableDateTime 
    : DateTime.Now; 

mà là

var dateTimeNullable1 = nullableDateTime.HasValue 
    ? nullableDateTime.Value 
    : DateTime.Now; 

Để trích dẫn của bạn phần 7.12 "Các nhà điều hành coalescing null" của spec C# 3.0 (xin lỗi cho định dạng hơi ropey):

Loại biểu thức a ?? b phụ thuộc vào ngụ ý chuyển đổi là avai lable giữa các loại toán hạng.Để sở thích, loại a ?? bA0, A, hoặc B, nơi A là loại a, B là loại b (với điều kiện là b có một loại), và A0 là loại cơ bản của A nếu A là một loại không có giá trị hoặc A nếu không.

Vì vậy, nếu aNullable<Something>, và b có thể được ngầm chuyển đổi sang Something, loại toàn bộ biểu thức sẽ Something. Như @Damien_The_Unbeliever đề xuất, số điểm của toán tử này là để kết hợp các giá trị rỗng!

+1

Cho đến nay tôi chỉ tìm kiếm [tài liệu MSDN trên '??'] (http://msdn.microsoft.com/en-us/library/ms173224.aspx) và [Sử dụng các kiểu Nullable] (http: // msdn .microsoft.com/vi-us/library/2cf62fcy.aspx). Chúng không bao giờ sử dụng 'var' trong các ví dụ đó nhưng gán cho một kiểu rõ ràng. Dù sao, rõ ràng là 'a ?? b' là ** không ** chính xác giống như 'a! = null? a: b' khi nói đến các loại nullable. – comecme

5

Để đi tất cả luật sư ngôn ngữ, trong giây lát. Từ C# spec (phiên bản 4):

7,13

Kiểu của biểu thức a ?? b phụ thuộc vào chuyển đổi tiềm ẩn có sẵn trên các toán hạng. Trong thứ tự ưu tiên, loại a ?? bA0, A, hoặc B, nơi A là loại a (với điều kiện là a có một loại), B là loại b (với điều kiện là b có một loại), và A0 là loại cơ bản của A nếu A là một loại có thể vô hiệu hóa hoặc A nếu không.

Vì vậy, ?? được xác định rõ ràng để thích loại cơ bản của biểu thức đầu tiên, nếu biểu thức đầu tiên đó là loại có thể không có giá trị.

Trong khi ngôn ngữ từ 7,14 (đối phó với ?:) chỉ thảo luận về các loại thực tế của xy, từ hình thức b ? x : y, và thảo luận ngầm chuyển đổi giữa hai loại.

Nếu một chuyển đổi ngầm (§6.1) tồn tại từ X thành Y, nhưng không phải từ Y đến X, sau đó Y là kiểu của biểu thức điều kiện

Kể từ Nullable(T) định nghĩa một ngầm chuyển đổi từ T đến Nullable(T) và chỉ một chuyển đổi rõ ràng từ Nullable(T) đến T, loại chỉ có thể có của biểu thức tổng thể là Nullable(T).