2010-10-09 38 views
6

thể Duplicates:
Deep Null checking, is there a better way?
C# elegant way to check if a property's property is nullLàm thế nào để tránh nhiều nếu kiểm tra vô

tôi phải làm một tra cứu trong một mô hình đối tượng sâu như thế này:

p.OrganisationalUnit.Parent.Head.CurrentAllocation.Person; 

là có anyway để đánh giá này và trả về null nếu có o f chuỗi là null (organizationalunit, cha mẹ, người đứng đầu, vv), mà không cần phải làm một

if (p.org == null && p.org.Parent == null && p.org.Parent.Head . . .  
+0

Cố gắng tránh loại tra cứu đó; xin vui lòng xem câu trả lời của tôi dưới đây để biết chi tiết. – CesarGon

Trả lời

8

Bạn đang tìm kiếm các toán tử tham chiếu null-an toàn ?. (còn gọi là chuyển hướng an toàn) mà một số ngôn ngữ (ví dụ Groovy) có, nhưng tiếc là C# không có toán tử này.

Hy vọng rằng nó sẽ được thực hiện một ngày nào đó ....

cũng this post Xem bởi Eric Lippert. Cú pháp mà anh ta đề xuất có là .?.

+0

Nó thường được gọi là toán tử tuyên truyền ** null ** hoặc ** toán tử điều kiện null **. –

+1

Hiện đã có trên C# 6: https://msdn.microsoft.com/en-us/library/dn986595.aspx –

7

Bạn đã nghe nói về số Law of Demeter chưa?

Việc có chuỗi các cuộc gọi dài như vậy không phải là một ý tưởng hay. Nó tạo ra sự phụ thuộc khủng khiếp giữa các lớp mà bạn không cần.

Trong ví dụ của bạn, lớp học chứa p phụ thuộc vào năm các lớp khác. Tôi đề nghị bạn đơn giản hóa mã của bạn và làm cho mỗi lớp kiểm tra các giá trị null ở một mức duy nhất, trong bối cảnh kiến ​​thức của riêng chúng.

+0

đồng ý nhưng được thực hiện trên cơ sở mã lớn, không thể tái cấu trúc tất cả trong một ngày :) – leora

+0

@ooo: Tôi hiểu. Trong trường hợp đó, tôi nghĩ bạn cần phải sử dụng chuỗi kiểm tra rỗng. Tôi sẽ cố gắng gói gọn nó trong một phương thức riêng để các phụ thuộc được cô lập và dễ dàng nhận ra. – CesarGon

0

Để trả lời câu hỏi ở tiêu đề của bạn, bạn có thể tránh bằng cách áp dụng 'luật của Demeter' và tạo ra một phương pháp gọi là GetHeadOfParentOrganizationalUnit()

Tôi không chắc chắn nếu các giải pháp áp dụng đối với trường hợp cụ thể của bạn, nhưng nó có giá trị nếu bạn có thể loại bỏ tất cả những kiểm tra null đó.

Xem thêm: a link

+1

nhưng sau đó hàm GetHeadofParent. .sẽ chỉ có cùng một kiểm tra null lồng nhau – leora

+1

@oooo - Không thực sự bạn bước vào một cấp tại một thời điểm. Mỗi lớp chỉ nói chuyện với cộng tác viên trực tiếp của nó, bạn không hack đi vào bên trong cộng tác viên để xé bỏ một số trạng thái lồng nhau ... * đọc lên luật của Demeter *. Từ wikipedia - Một bất lợi của Luật Demeter là đôi khi nó đòi hỏi phải viết một số lượng lớn các phương thức "wrapper" nhỏ để truyền các lời gọi phương thức tới các thành phần. Hơn nữa, giao diện của lớp có thể trở nên cồng kềnh khi nó lưu trữ các phương thức cho các lớp được chứa, dẫn đến một lớp không có giao diện gắn kết. Nhưng điều này cũng có thể là một dấu hiệu của thiết kế OO xấu. – Gishu

6

Check-out this article. Nó trình bày một giải pháp tuyệt vời cho phép bạn viết những thứ như thế:

p.With(x => x.OrganisationalUnit) 
.With(x => x.Parent) 
.With(x => x.Head) 
.With(x => x.CurrentAllocation 
.With(x => x.Person); 
-2

Bạn có thể sử dụng xử lý ngoại lệ cơ bản để nắm bắt điều đó. Tôi không điên về giải pháp đó, nhưng nó là một lựa chọn. Nếu các giá trị null lồng nhau này là hoạt động bình thường, ngoại lệ có thể không phải là câu trả lời đúng:

public class A 
{ 
} 
public class B 
{ 
    public A a; 
} 
public class C 
{ 
    public B b; 
} 
class Program 
{ 
    static A GetA(C c) 
    { 
     A myA; 
     try 
     { 
      myA = c.b.a; 
     } 
     catch 
     { 
      myA = null; 
     } 
     return myA; 
    }   

    static void Main(string[] args) 
    { 
     C theC = new C(); 
     theC.b = new B(); 
     theC.b.a = new A(); 
     A goodA = GetA(theC); 
     if (goodA != null) 
     { 
      Console.WriteLine("Expected nominal path."); 
     } 
     else 
     { 
      Console.WriteLine("Unexpected nominal path."); 
     } 
     theC.b.a = null; 
     A badA = GetA(theC); 
     if (badA == null) 
     { 
      Console.WriteLine("Expected off-nominal path."); 
     } 
     else 
     { 
      Console.WriteLine("Unexpected off-nominal path."); 
     } 

    } 

} 
+0

Gọi hệ thống xử lý ngoại lệ có vẻ quá mức đối với các hoạt động bình thường; Tuy nhiên như bạn nói nó là một giải pháp, suy nghĩ bên ngoài hộp. –

+0

@ John K: Tôi đồng ý - cách duy nhất tôi từng thực sự xem xét việc này là nếu bất kỳ null lồng nhau nào đại diện cho trạng thái "bị hỏng". Thêm vào đó là vấn đề của việc không biết dereference đã phá vỡ hệ thống, và hiệu suất hit. Nhưng nó là một công cụ trong hộp ... – PatrickV

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