2011-07-19 22 views
6

Tôi mệt mỏi viết:Kết thúc hoạt động cao hơn trong hệ thống phân cấp

if(objectA!=null) 
return; 

hay:

if(objectB==null) 
return; 

Vì vậy, tôi đã hy vọng để rút ngắn đoạn này, để một cái gì đó như thế này:

Returns.IfNull(objectA); 

nó là khá phù hợp với chiều dài tương tự nhưng thường có vài đối tượng để kiểm tra và thêm params như tham số có thể rút ngắn:

if(objectA==null || objectB!=null || objectC!=null) 
return; 

tới:

Returns.IfNull(objectA,objectB,objectC); 

Về cơ bản hoạt động IfNull có để có được quyền truy cập vào chức năng một bước cao hơn trong stack trace và hoàn thành nó. Nhưng đó chỉ là ý tưởng, tôi không biết nếu nó thậm chí có thể. Tôi có thể tìm thấy simililar logic trong một số lib?

+0

Điều bạn muốn về bản chất là một phương thức mở rộng - mặc dù hơi khác với lớp 'Returns' ... – IAbstract

+1

Phương thức IfNull của bạn biết có nên kiểm tra là null hay không null như ví dụ trước? –

+1

@IAbstract: Ngay cả khi đó, một phương thức mở rộng không thể "trả lại" hàm ở trên nó trong ngăn xếp –

Trả lời

7

Không, về cơ bản bạn đang yêu cầu chức năng thoát khỏi hàm cao hơn chính nó mà không được mong muốn cũng không thực sự có thể trừ khi bạn ném một ngoại lệ (không trả lại cho mỗi người). Vì vậy, bạn có thể thực hiện kiểm tra if-null-return đơn giản và súc tích của bạn, hoặc những gì bạn có thể làm ở đó thay vì ném một ngoại lệ được xác định rõ ràng, nhưng tôi không khuyên bạn nên ngoại lệ cho điều khiển luồng. Tuy nhiên, nếu đây là những trường hợp ngoại lệ (lỗi), hãy xem xét việc ném một ArgumentNullException() và xử lý nó khi thích hợp.

Bạn có thể viết một số phương pháp helper để ném ArgumentNullException() cho bạn, tất nhiên, để làm sạch nó lên một chút:

public static class ArgumentHelper 
    { 
     public static void VerifyNotNull(object theObject) 
     { 
      if (theObject == null) 
      { 
       throw new ArgumentNullException(); 
      } 
     } 

     public static void VerifyNotNull(params object[] theObjects) 
     { 
      if (theObjects.Any(o => o == null)) 
      { 
       throw new ArgumentNullException(); 
      } 
     } 
    } 

Sau đó, bạn có thể viết:

public void SomeMethod(object obj1, object obj2, object obj3) 
{ 
    ArgumentHelper.VerifyNotNull(obj1, obj2, obj3); 

    // if we get here we are good! 
} 

Nhưng một lần nữa , đây là ngoại lệ và không phải là "trả lại" của phương thức trước đó trong ngăn xếp, điều này không thể trực tiếp thực hiện được.

+1

Người gọi vẫn có thể bắt được ngoại lệ và từ chối không trả lại sớm, tuy nhiên. –

+1

Rất đúng :-) nhưng đó là cách duy nhất để nói phương pháp trên nó có khả năng thoát (nếu không được) ... –

+1

Có lẽ một goto có thể hoạt động: p: D –

0

Bạn không thể gọi phương thức khác và mong đợi nó trở về mức độ thoải mái của phương pháp hiện tại (bạn có thể nếu chúng tôi có thứ gì đó như kiểu chuyển tiếp liên tục; chẳng hạn, chúng tôi không).

Bạn có thể nói:

if(new[] { objectA, objectB, objectC }.Any(x => x != null)) { 
    return; 
} 

Hoặc:

if(new[] { objectA, objectB, objectC }.AnyAreNotNull()) { 
    return; 
} 

Ở đây, AnyAreNotNull là:

public static class EnumerableExtensions { 
    public static bool AnyAreNotNull<T>(this IEnumerable<T> source) { 
     Contract.Requires(source != null); 
     return source.Any(x => x != null); 
    } 
} 

Nhưng thực sự, không có gì sai trái với chỉ viết code thông thường cho là tình huống này.

+4

Điều đó thật xấu xí, và tôi sẽ tranh cãi, khó hiểu hơn là chỉ làm việc kiểm tra cơ bản mà anh ta đã làm ở trên.:) –

+0

Vâng, trong trường hợp này tôi muốn tranh luận ít hơn ... Tạo một colleciton chỉ để xem nếu có là null có vẻ hơi quá mức. Cá nhân tôi thích kiểm tra chúng và sau đó ném ArgumentNullException, nhưng đó là cung cấp anh ta tốt với trường hợp ngoại lệ ... –

+0

@George: Vào thời điểm đó chúng tôi đang trong thỏa thuận. – jason

0

Không, phương pháp không thể trả về phương thức ở trên nó.

Tốt nhất bạn có thể làm là tạo phương thức trả về true nếu bất kỳ tham số nào của nó là rỗng, sau đó thực hiện if (ReturnHelper.AllNull(obj1, obj2, obj3)) return; nhưng tôi muốn nói điều này ít dễ đọc hơn.

1

Bạn đang yêu cầu thứ gì đó mà chỉ nhà thiết kế ngôn ngữ mới có thể sửa chữa cho bạn. Tôi đã đề xuất một điều bởi myself. The.? toán tử trả về từ phương thức hiện tại với giá trị trả về mặc định khi đối số còn lại là null.

return appSettings.?GetElementKey(key).?Value ?? ""; 

Có lẽ chúng ta sẽ thấy nó một ngày nào đó trong C# 6?

+0

Tôi hy vọng bản thân mình cho một cái gì đó như thế – Twelve

1

Để thực hiện điều tra so sánh tương tự một lần tôi định nghĩa các phương pháp sau đây mở rộng:

/// <summary> 
/// Returns whether the object equals any of the given values. 
/// </summary> 
/// <param name = "source">The source for this extension method.</param> 
/// <param name = "toCompare">The objects to compare with.</param> 
/// <returns> 
/// True when the object equals any of the passed objects, false otherwise. 
/// </returns> 
public static bool EqualsAny(this object source, params object[] toCompare) 
{ 
    return toCompare.Any(o => o.Equals(source)); 
} 

Nó có thể đơn giản hóa kiểm tra không cần thiết, ví dụ:

string someString = "bleh"; 
bool anyEquals = someString.EqualsAny("bleh", "bloeh"); 

Trong trường hợp của bạn, nơi bạn kiểm tra nhiều kiểm tra rỗng bạn có thể sử dụng nó như sau:

if (EqualsAny(null, objectA, objectB, objectX)) return; 

Lưu ý khác, mã của bạn nhắc tôi về số Code Contracts cho phép bạn xác định các điều kiện trước và sau. Trong trường hợp này là kịch bản của bạn - có lẽ không phải vì tôi không thấy lý do tại sao bạn gọi return - nó có thể bạn quan tâm. Một phần của nó có sẵn miễn phí trong .NET 4.0.

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