2010-04-07 72 views
2

我花了大部分時間在C#中,並試圖找出哪一個是處理異常的最佳實踐,並乾淨地從被調用的方法返回錯誤消息回到調用方法。返回什麼?錯誤字符串,布爾與錯誤字符串輸出,或無效異常

例如,這裏有一些ActiveDirectory驗證碼。 請想象一下這個方法的類的一部分(而不僅僅是一個獨立的功能。)

bool IsUserAuthenticated(string domain, string user, string pass, out errStr) 
{ 
    bool authentic = false; 
    try 
    { 
    // Instantiate Directory Entry object 
    DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass); 

    // Force connection over network to authenticate 
    object nativeObject = entry.NativeObject; 

    // No exception thrown? We must be good, then. 
    authentic = true; 
    } 
    catch (Exception e) { errStr = e.Message().ToString(); } 
    return authentic; 
} 

做這種方式的優點是明確的YES或NO,你可以嵌入就在你的IF-THEN - 無效的聲明。缺點是,它也使用該方法提供一個字符串來獲取錯誤回到需要的人(如果有的話)。

我想我可以重載這個方法使用相同的參數減去「出errStr」,但忽略錯誤似乎是一個壞主意,因爲可能有很多原因造成這樣的失敗...

或者,我可以編寫一個方法,返回一個錯誤字符串(而不是使用「out errStr」),其中返回空字符串意味着用戶認證正常。

string AuthenticateUser(string domain, string user, string pass) 
{ 
    string errStr = ""; 
    try 
    { 
    // Instantiate Directory Entry object 
    DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass); 

    // Force connection over network to authenticate 
    object nativeObject = entry.NativeObject; 
    } 
    catch (Exception e) { errStr = e.Message().ToString(); } 
    return errStr; 
} 

但這似乎是一種「弱」的做事方式。

或者我應該只是讓我的方法「無效」,只是不處理異常,以便它傳遞迴調用函數?

void AuthenticateUser(string domain, string user, string pass) 
{ 
    // Instantiate Directory Entry object 
    DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass); 

    // Force connection over network to authenticate 
    object nativeObject = entry.NativeObject; 
} 

這似乎是最理智的我(出於某種原因)。然而,與此同時,將這兩行代碼包裝在這兩行中的唯一真正優點就是我不需要包含「LDAP://」字符串。這種做法的缺點是用戶必須將此方法放在try-catch塊中。

想法?

有沒有另一種方法做到這一點,我沒有想到?

回答

6

沒有「一刀切」。如果您返回一個標誌,那麼可以很容易地使用if()中的方法和循環。例外情況總是需要大量的鍋爐板代碼。如果你只是想要一個字符串,你可以顯示給用戶(比如說,在一個Web UI中),返回錯誤字符串(或者null「沒有錯誤」)也是很好的。

但是大多數情況下,我拋出了一個異常(並且在Java中是RuntimeException的一個子類),因爲這允許我返回多個關於錯誤的單個信息(如:哪個文件導致錯誤?哪條線/列?我在做什麼?表格中的哪個字段應該被標記爲非法?等等)。

在你的情況下,你不能在你的方法中處理異常,所以你不應該抓住它。只有在你能做點什麼時才抓住它。

2

不處理異常或返回任何類型的消息。讓你的方法的消費者照顧這一點。

3

在這個例子中,我同意,你應該讓異常流向消費者。但是,作爲您強調的方法的替代方案,請考慮此方法。

您可以使用響應對象來保存出來的方法運行的信息,例如:

public abstract class BaseResponse 
{ 
    public bool IsOk { get; protected set;} 
    public string Message { get; protected set; } 
} 

public class AuthenticationResponse: BaseResponse 
{ 
    public AuthenticationResponse(bool isOk): this(isOk, "") {} 
    public AuthenticationResponse(bool isOk, string message) 
    { 
    IsOk = isOk; 
    Message = message; 
    } 
} 

AuthenticationResponse IsUserAuthenticated(string domain, string user, string pass) 
{ 
    bool authentic = false; 
    string errStr; 
    try 
    { 
    // Instantiate Directory Entry object 
    DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, user, pass); 

    // Force connection over network to authenticate 
    object nativeObject = entry.NativeObject; 

    // No exception thrown? We must be good, then. 
    authentic = true; 
    } 
    catch (Exception e) { errStr = e.Message().ToString(); } 
    return new AuthenticationResponse(authentic, errStr); 
} 

然後才能使用它你的if語句:

AuthenticationResponse response; 
if((response = IsUserAuthenticated("domain", "user", "pass")).IsOk) 
{ 
    // do successful activity 
} else { 
    Console.WriteLine(response.Message) 
} 

訣竅是賦值操作的返回值是分配的值。所以,我們可以在同一行中完成分配和有效檢查。如果您不需要堅持調用的結果,您可以簡單地調用該方法並檢查IsOk屬性。

if(IsUserAuthenticated("domain", "user", "pass").IsOk) 
{ 
    // do successful activity 
} 

然後,您可以構建自定義響應對象,以根據需要返回方法中任意值的組合。

+0

+1 - 哇!這非常聰明!儘管我耿耿於懷正在做的事情,但我不確定我是否會在實踐中實施它。也許我只需要讓它在我的大腦中燉一段時間,也許我會變得適應它...... :-)謝謝! – Pretzel 2010-04-07 17:12:33