2013-05-14 27 views
5

Tôi đang làm việc bên trong phương thức thực hiện một loạt kiểm tra xác thực và bất kỳ kiểm tra nào không thành công, gọi số Action<string> để chạy một số mã từ chối phổ biến. Các thiết lập được một cái gì đó tương tự như sau:Trả lại từ phương thức gốc bên trong Hành động <string>

public void ValidationMethod() { 
    Action<string> rejectionRoutine = (rejectionDescription) => { 
     // do something with the reject description 
     // other common code 
    }; 

    if (condition != requiredValue) { 
     rejectionRoutine("Condition check failed"); 
     // I currently have to put `return` here following every failed check 
    } 

    // many more checks following this 
} 

Trong hệ thống này một lần một séc đã thất bại xác nhận tôi không có nhu cầu để xác nhận phần còn lại, tôi chỉ muốn chạy mã từ chối phổ biến bên trong hành động và thoát khỏi phương pháp . Hiện nay để làm điều này tôi chỉ cần return trên dòng tiếp theo sau một cuộc gọi đến rejectionRoutine. Tôi tự hỏi nếu có một cách tôi có thể kết hợp khả năng trả lại hoặc chấm dứt thực hiện phương pháp cha mẹ từ bên trong Action?

Tôi biết điều này hơi khó tính nhưng tôi cảm thấy nó tốt hơn cho khả năng mở rộng xuống đường nếu người khác cần thêm kiểm tra xác thực bổ sung (họ sẽ không phải lo lắng về việc đưa trở lại tất cả nơi) cũng như đóng gói hành vi chung của việc thực hiện kết thúc bên trong mã được cho là phổ biến đối với những trường hợp này.

Trả lời

6

Một cách để làm sạch mã lên một chút sẽ là ngoại suy tất cả các kiểm tra ra một bộ sưu tập:

Dictionary<Func<bool>, string> checks = new Dictionary<Func<bool>, string>() 
{ 
    {()=> condition != requiredValue, "Condition check failed"}, 
    {()=> otherCondition != otherRequiredValue, "Other condition check failed"}, 
    {()=> thirdCondition != thirdRequiredValue, "Third condition check failed"}, 
}; 

Nếu điều quan trọng là cho kiểm tra để chạy theo một thứ tự đặc biệt (mã này có một thứ tự không thể đoán trước), sau đó bạn muốn sử dụng một cái gì đó giống như một List<Tuple<Func<bool>, string>> thay thế.

var checks = new List<Tuple<Func<bool>, string>>() 
{ 
    Tuple.Create<Func<bool>, string>(()=> condition != requiredValue 
     , "Condition check failed"), 
    Tuple.Create<Func<bool>, string>(()=> otherCondition != otherRequiredValue 
     , "Other condition check failed"), 
    Tuple.Create<Func<bool>, string>(()=> thirdCondition != thirdRequiredValue 
     , "Third condition check failed"), 
}; 

Sau đó bạn có thể sử dụng LINQ để làm xác nhận:

var failedCheck = checks.FirstOrDefault(check => check.Item1()); 
if (failedCheck != null) 
    rejectionRoutine(failedCheck.Item2); 
+0

Ahhh Servy, tâm trí tuyệt vời nghĩ như nhau.Tôi đã viết mã đã gần như giống hệt với điều này trước khi tôi tìm thấy một vài điểm mà nó không có ý nghĩa. Có một số kiểm tra sẽ ném ngoại lệ nếu chúng được đánh giá khi kiểm tra trước đó nên có teriminated. I E. check1 là giá trị! = null, check2 có thể làm điều gì đó với giá trị giả định rằng nó không thể là null nếu chúng ta có được điều này xa –

+0

@ JesseCarter Sau đó, như tôi đã nói ở phần cuối, bạn sẽ cần sử dụng 'List , string >> '. Nó chỉ là một chút nhiều mã. – Servy

+0

Có lẽ tôi đang bối rối về cách bool trong Func sẽ được đánh giá? Việc đánh giá thực tế giá trị bool có bị trì hoãn cho đến khi Func được gọi không? Tôi giả định rằng nó sẽ được đánh giá ngay khi Func được tạo ra –

1

Không có ý nghĩa gì khi trả về từ phương thức người gọi bên trong biểu thức lambda.
(nếu bạn gọi nó là sau khi phương pháp này chạy xong?)

Thay vào đó, bạn có thể thay đổi nó thành một Func<string, Whatever> và trở về giá trị của nó:

return rejectionRoutine("Condition check failed"); 
+0

Các hành động sống tại địa phương bên trong của phương pháp này vì vậy tôi không thấy làm thế nào nó có thể được gọi nếu phương pháp này đã được hoàn tất chạy? Nếu tôi trả lại một cái gì đó từ một Func thay vào đó tôi vẫn sẽ phải làm một nếu (returnValue == cái gì đó) trở lại sau mỗi kiểm tra. Hay tôi thiếu cái gì đó với cách tiếp cận này? –

+0

@JesseCarter: Không có gì ngăn cản bạn vạch trần đại biểu bên ngoài phương pháp. Tôi không chắc ý bạn là gì. – SLaks

+0

Tôi đã chỉnh sửa ví dụ mã trong câu hỏi của mình, Hành động chỉ tồn tại trong phạm vi của phương thức Xác thực xung quanh. Tôi không thấy làm thế nào nó có thể được gọi là bất cứ nơi nào ngoại trừ bên trong của phương pháp đó. –

0

Để thay thế cho giải pháp SLaks bạn cũng có thể ném một ngoại lệ trong rejectionRoutine nếu thiết kế của bạn cho phép.

+0

Thật không may tôi không nghĩ rằng ném một ngoại lệ phù hợp với thiết kế hiện tại. Cảm ơn những suy nghĩ mặc dù –

+3

Ngoại lệ không nên được sử dụng cho dòng điều khiển bình thường; chúng nên được sử dụng cho các tình huống đặc biệt. – Servy

+0

Suy nghĩ của tôi chính xác Servy và tôi chắc chắn rằng sẽ là sự đồng thuận trong đánh giá mã của tôi nếu tôi cố gắng thực hiện theo cách đó –

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