2012-02-23 169 views
1

我有一個Dictionary<string, T>私有字段(users),其中string鍵代表用戶名。我爲這個類寫了一些方法,例如GetValue(string userid)方法返回與指定用戶名關聯的T對象。處理自定義類中的異常

我會處理這個類中可能出現的異常,這些異常是由Dictionary引起的。例如:

  • 如果指定鍵爲空,則Dictionary拋出ArgumentNullException;
  • 如果指定的鍵不存在於Dictionary中,則會拋出KeyNotFoundException

第一種方法可以趕上由Dictionary拋出的異常,並重新拋出同樣的例外或拋出自定義異常。

public T GetValue(string userid) 
{ 
    try 
    { 
     return users[userid]; 
    } 
    catch(ArgumentNullException ex1) 
    { 
     // re-throw the same exception 
    } 
    catch(KeyNotFoundException ex2) 
    { 
     throw new UserIdNotFoundException("The specified userid does not exist.", ex2); // custom exception 
    } 
} 

第二種方法可避免捕捉異常,但檢查導致他們的條件,並拋出適當的例外。

public T GetValue(string userid) 
{ 
    if (userid != null) 
    { 
     if(users.ContainsKey(userid)) 
      return users[userid]; 
     else throw new UserIdNotFoundException("The specified userid does not exist.", ex2); // custom exception 
    } 
    else throw new ArgumentNullException(...); 
} 

第三種方法是類似於第二之一,但它使用了DictionaryTryGetValue方法。

public T GetValue(string userid) 
{ 
    if (userid != null) 
    { 
     T value; 
     if(users.TryGetValue(userid, out value)) 
      return value; 
     else throw new UserIdNotFoundException("The specified userid does not exist.", ex2); // custom exception 
    } 
    else throw new ArgumentNullException(...); 
} 

每種方法的優點和缺點是什麼? 的best practices for handling exceptions說:

如果該事件是真正的例外,是錯誤的,因爲使用更少的代碼在正常情況下,執行異常 處理比較好... 如果事件發生日常使用編程的方法來檢查 錯誤比較好...

在我的情況下GetValue(string userid)方法將被調用很少,但是類的潛在用戶可以使用它非常頻繁。

回答

2

當存在避免底層數據類型中的異常的實用和高性能的方法時,即使您最終會自行拋出異常,也可能是一個好主意。使用TryGetValue幾乎總是從字典中提取可能包含或不包含特定項目的東西的正確方法。

除此之外,你的內部方法調用拋出異常,你知道它們是什麼意思,除非你確定所有這些異常在代碼中出現時總是具有相同的語義含義,你打電話。否則,假設嘗試添加重複的用戶時,Dictionary會拋出ArgumentException。如果您將此滲透爲ArgumentException而不是將其包裝爲其他內容,並且稍後可以使用AddUser方法中某處的代碼爲其他內容拋出ArgumentException,則可能很難幫助您的調用者區分一個ArgumentException由一個重複的用戶造成,而一個ArgumentException由於其他原因而發生。

2

ContainsKeyTryGetValue兩個方法可避免拋出方法KeyNotFoundException

Diffrence之間ContainsKey它僅僅檢查天氣鍵存在或不存在且比得到的值,但TryGetValue不僅檢查鍵存在或不存在,但也獲取該密鑰的值。

TryGetValue方法很容易使用比ContainsKey的方法,但只有當你想檢查集合中的關鍵,也想獲得與它相關的值。如果您只想檢查密鑰是否存在,或僅僅使用ContainsKey。

瞭解更多:Dictionary Object (ContainsKey Vs. TryGetValue)可能會對您有所幫助。

2

這取決於你的班級的預期目的。例如,如果您的類充當Dictionary包裝器,則客戶端可能會傳播典型的Dictionary類似的錯誤/異常行爲。如果你的班級正在實施更復雜的(最有可能的),我會說你最好向調用者提出自己的錯誤。至於採取哪種方法,請在正常的Dictionary交互中進行相同的輸入驗證。換句話說,如果您在添加到Dictionary之前通常檢查ContainsKeyTryGetValue,請繼續在此處執行此操作,但不需要拋出新的異常。相反,用他們可能理解的方式將錯誤報告給調用者。他們不應該知道你在底層使用Dictionary

0

第三執行是最好的,因爲它是最快和最短的。

實現是次優的:它訪問字典兩次,一次檢查是否存在,第二次是獲取值。

第一實現是最差的:

  • 這不是萬一功能上等同參數爲null。
  • 它從嘗試聲明收到性能損失 - 編譯器將不得不在堆棧上設置一些數據顯然。
  • 還有一個風格問題,在我看來,程序大量使用捕獲陳述。對異常做的最好的事情往往是讓他們冒泡直到他們可以被記錄或者可以完成一些事情。