2014-09-04 18 views
11

Null propagating operator/Conditional access expression đến trong trông giống như một tính năng khá tiện dụng. Nhưng tôi tò mò nếu nó sẽ giúp giải quyết vấn đề kiểm tra nếu một thành viên trẻ không phải là null và sau đó gọi một phương thức Boolean trên cho biết thành viên trẻ bên trong một khối nếu:C# Null tuyên truyền nhà điều hành/biểu thức truy cập có điều kiện và nếu khối

public class Container<int>{ 
     IEnumerable<int> Objects {get;set;} 
    } 

    public Container BuildContainer() 
    { 
     var c = new Container(); 

     if (/* Some Random Condition */) 
     c.Objects = new List<int>{1,2,4}; 
    } 

    public void Test() 
    { 
     var c = BuildContainer(); 

     //Old way 
     if (null != c && null != c.Objects && c.Objects.Any()) 
     Console.Write("Container has items!"); 


     //C# 6 way? 
     if (c?.Object?.Any()) 
      Console.Write("Container has items!"); 
    } 

sẽ c?.Object?.Any() biên dịch? Nếu các nhà điều hành truyền ngắn mạch (tôi giả định đó là đúng hạn) để null sau đó bạn có if (null), mà không hợp lệ.

Đội C# có giải quyết được mối lo ngại này hoặc tôi có thiếu trường hợp sử dụng dự định cho toán tử tuyên truyền không?

Trả lời

27

Nó sẽ không hoạt động theo cách này. Bạn chỉ có thể bỏ qua phần giải thích và xem mã bên dưới :)

Như bạn đã biết ?. toán tử sẽ trả về giá trị rỗng nếu thành viên con là rỗng. Nhưng điều gì sẽ xảy ra nếu chúng tôi cố gắng để có được một thành viên không thể vô hiệu hóa, như phương pháp Any(), trả về bool? Câu trả lời là trình biên dịch sẽ "bọc" một giá trị trả về trong Nullable<>. Ví dụ: Object?.Any() sẽ cung cấp cho chúng tôi bool? (là Nullable<bool>), không phải bool.

Điều duy nhất mà không cho phép chúng ta sử dụng biểu thức này trong báo cáo if là nó không thể được ngầm Casted đến bool. Nhưng bạn có thể làm so sánh một cách rõ ràng, tôi thích so với true như thế này:

if (c?.Object?.Any() == true) 
    Console.Write("Container has items!"); 

Thanks to @DaveSexton có một cách khác:

if (c?.Object?.Any() ?? false) 
    Console.Write("Container has items!"); 

Nhưng đối với tôi, so với true vẻ tự nhiên hơn :)

+0

Vì vậy, '.' không thực sự trả về null? Nó trả về một 'Nullable'? –

+0

@PhilipPittle nó kết thúc tốt đẹp giá trị trả về trong 'Nullable' cho giá trị và kiểu nguyên thủy –

+2

Hoặc, một số có thể thích sử dụng toán tử kết hợp null:' if (c? .Objects? .Any() ?? false) {...} ' –

4

Toán tử có điều kiện sẽ trả về null hoặc giá trị ở cuối biểu thức. Đối với value types Nó sẽ trả lại kết quả trong Nullable<T>, vì vậy trong trường hợp của bạn, nó sẽ là Nullabe<bool>. Nếu chúng ta nhìn vào ví dụ trong tài liệu cho Upcoming Features in C#(quy định here), nó có một ví dụ:

int? first = customers?[0].Orders.Count(); 

Trong ví dụ trên, thay vì int, Nullable<int> sẽ được trả lại. Đối với bool, nó sẽ trả về Nullable<bool>.

Nếu bạn cố gắng đoạn mã sau vào Visual Studio "14" CTP:

Nullable<bool> ifExist = c?.Objects?.Any(); 

Kết quả của dòng trên sẽ là một Nullable<bool>/bool?.Sau đó bạn có thể làm việc so sánh như:

Sử dụng null-coalescing operator ??

if (c?.Object?.Any() ?? false) 

Sử dụng Nullable<T>.GetValueOrDefault Phương pháp

if ((c?.Objects?.Any()).GetValueOrDefault()) 

Sử dụng so sánh với true

if (c?.Objects?.Any() == true) 
Các vấn đề liên quan