2012-04-03 182 views
2

我有下面的代碼有什麼異常:我應該處理

 public void OpenFile(string FileName) 
     { 
      if (FileName == null) 
       throw new ArgumentNullException("FileName", "OpenFile: Filename is null"); 


      List<int> readItems = new List<int>(); 
      using (StreamReader reader = new StreamReader(FileName)) 
      { 
       string line; 
       int batchItem; 
       while ((line = reader.ReadLine()) != null) 
       { 
        if (int.TryParse(line, out batchItem)) 
        { 
         readItems.Add(batchItem); 
        } 
       } 
      } 

      CurrrentFile = FileName; 
      FileInfo f = new FileInfo(FileName); 
      lock (LockObject) 
      { 
       TextWriter = f.AppendText(); 
       TextWriter.AutoFlush = true; 
      } 

      if (readItems.Count > 0) 
       FileOpened(readItems); 


     } 

我試圖發現可能的問題,例如:/文件名是空的。

在,捕捉和記錄異常我顯然具有由StreamReader構造和FileInfo構造函數拋出catch(ArgumentNullException ex)

我應該還可以抓住可能出現的異常類?

我知道這聽起來很愚蠢,但我想知道是否應該對我拋出的異常有明確的捕獲,然後發現一個普通的異常捕獲它是否是catch(Exception ex)或者嘗試捕獲上述代碼並重新拋出自定義異常。否則,我的try/catch塊有大約12個獨立的catch語句!

+2

向Eric Lippert的有關不同種類的例外和正確方法的文章規定[鏈接](http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx)來處理它們。 – 2012-04-03 08:46:57

+0

@FrédéricHamidi但是在StreamReader/FileInfo的情況下,我不能做很多事情。如果我檢查自己的文件名是無效的,我會自己拋出異常,並有一個捕獲,所以我並沒有真正阻止任何事情 – 2012-04-03 08:53:33

回答

4

一般情況下,如果你遵循一些簡單的規則,你可以大大簡化你的異常處理代碼。

1.只有捕獲並處理異常你其實可以做一些

如果你不能真正從異常中恢復,那麼你不應該趕上它。讓例外冒泡到最高點(通常是用戶界面)。

當您確實捕獲異常時,您應該捕獲非常特定的異常,並儘可能避免泛型異常處理。

try 
{ 
    DoSomeStuff(); 
} 
catch(HolyCrapItBlewedUpException ex) 
{ 
    RecoverFromExplosion(); 
} 
catch(Exception ex) 
{ 
    //I really have no idea what happened, and I can't do 
    // anything about it, but I'm going to catch the 
    // exception anyway cause it makes me feel better 
} 

咳嗽例外上面的規則,但是這給我們帶來了我們的第二條規則。

2。只有使用通用的異常處理進行日誌記錄和執行隱藏

既然你應該讓你的異常一直冒泡到最高層,那麼任何讓它到頂端的東西都是一個bug。此時,您應該記錄該異常並向用戶顯示一些友好的消息。

try 
{ 
    DoSomeStuff(); 
} 
catch(Exception ex) 
{ 
    //At this point it's a bug... we need to squash it! 
    LogException(ex); 
    ShowUserRecoveryOptions(); 
} 

您可能想要做的另一個地方是爲了維護一個API的契約並隱藏實現細節。如果最終用戶正在調用方法,他們可能不需要知道發生的每一個可能的問題,只是它沒有工作。

public void MakeMeASandwich() 
{ 
    try 
    { 
     MakeCallerASandwich(); 
    } 
    catch(SecurityException ex) 
    { 
     //It's still best to distinguish between certain exceptions 
     // as long as it makes sense to the caller. 
     throw new NoIWillNotMakeYouASandwichException(ex); 
    } 
    catch(Exception ex) 
    { 
     throw new SorryICantMakeYouASandwichException(ex); 
    } 
} 

3.避免像瘟疫一樣的例外!

例外應該是,非常...例外!在大多數情況下,您應該能夠預先通過簡單編碼來避免異常。一個真正的例外應該代表你無法預測會發生的事情。一個簡單的例子是檢查文件的存在。

try 
{ 
    File.Open("blah.txt"); 
} 
catch(FileNotFoundException ex) 
{ 
    File.Create("blah.txt"); 
} 

在這個例子中,我知道這是可能的文件也就不存在了,所以,我應該寫代碼,以確保這種情況下幾乎從未發生過。現在

var fileName = "blah.txt"; 

if(!File.Exists(fileName)) 
    File.Create(fileName); 

File.Open(fileName); 

,它仍然有可能對FileNotFoundException在這裏拋出,但我們會如何處理呢?顯然這個代碼不能再做任何事情,因爲發生了一些真正的事情EXCEPTIONAL。我們可以讓異常冒泡到下一層,因爲在這裏我們可以做的沒有意義。

0

使用try catch 如果有一個錯誤,你可以在catch部分捕獲它。先使用特定異常,稍後再使用通用異常。

1

請務必確保您的常規異常即SystemException/ApplicationException/Exception catch子句處於最後。所以準備明顯。在你的情況SecurityException,FileNotFound,PathNotFound等例外。請檢查這些API的MSDN文檔以及它們拋出的各種異常情況。

製作泛型異常的問題永遠不會知道問題到底是什麼,甚至FxCop也會給出警告。沒有問題,如果你的catch子句更多,但只要確保你分裂並捕獲異常。例如,如果我們在不同的場合打開2個文件,則分別抓住每個文件而不是一個文件。

1

我是否也應該注意到StreamReader構造函數和FileInfo構造函數拋出的可能異常?

爲了保持簡短:您能否做出合理的事情,知道這些異常是否被拋出?如果是的話,趕上他們,並做到這一點。如果沒有,讓它破裂。