1

我有檢查數據庫中記錄的圖像名稱的方法。如果有這樣的話,我嘗試用記錄的路徑加載圖像。如果沒有我加載默認圖像。正確的地方處理文件沒找到異常在哪裏?

首先,我有我的整個方法的try-catch塊,其中catch(Exception ex)不管是什麼我剛回到Error loading image例外:

if (File.Exists(imgPath + "\\" + imageName)) 
    { 
     try 
     { 
      using (var temp = new Bitmap(imgPath + "\\" + imageName)) 
      { 
       pictureBox1.Image = new Bitmap(temp); 
      } 

      if (pictureBox1.Image.Width > defaultPicBoxWidth) 
      { 
       pictureBox1.Width = defaultPicBoxWidth; 
      } 
     } 
     catch (Exception ex) 
     { 
      logger.Error(ex.ToString()); 
      MessageBox.Show("Error loading image!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
    } 

後來我想通了,有時候我可能會在數據庫中的記錄,但由於某種原因,該文件可能會丟失,所以我爲補充檢查:

if (imageName != null && !File.Exists(imgPath + "\\" + imageName)) 

現在我需要爲這種情況下正確的消息了。我得出的結論是,我可以 - 使用幾個try-catch塊來處理這些部分或拋出異常並處理調用該方法的異常。

我選擇了第二個選項,現在整個代碼爲:

if (imageName != null && !File.Exists(imgPath + "\\" + imageName)) 
    { 
     throw new FileNotFoundException(); 
    } 

    if (File.Exists(imgPath + "\\" + imageName)) 
    { 
     //try 
     //{ 
      using (var temp = new Bitmap(imgPath + "\\" + imageName)) 
      { 
       pictureBox1.Image = new Bitmap(temp); 
      } 

      if (pictureBox1.Image.Width > defaultPicBoxWidth) 
      { 
       pictureBox1.Width = defaultPicBoxWidth; 
      } 
     //} 
     //catch (Exception ex) 
     //{ 
     // logger.Error(ex.ToString()); 
     // MessageBox.Show("Error loading image!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     //} 
    } 

而這正是我所說的方法:

try 
       { 
        //The name of the method described above 
        LoadSavedOrDefaultImage(imageInfo, entity.Picture, txtCode.Text, imageLocation); 
       } 
       catch (FileNotFoundException ex) 
       { 
        logger.Error(ex.ToString()); 
        MessageBox.Show("Error loading image! The file wasn't found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
       } 
       catch (Exception ex) 
       { 
        LogErrorAndShowMessage(ex, Resources.ERROR_LOAD); 
       } 

我喜歡這個更好,但我不能確切地說爲什麼。一般問題是 - 這是處理異常的正確方法。更具體的一個 - 在我的確切情況下,放置try-catch區塊的更好的地方是哪裏?對我來說,在方法本身中是很有意義的,因爲這樣我就不需要編寫這些塊,我在任何地方都會調用這個方法,這樣就更加封裝了。另外現在有兩個try-catch塊,但是如果將來邏輯改變了,我可能想要拋出更多不同的異常,這是保持異常處理在方法本身中的另一個原因,而不是它被調用的地方,但另一方面...想讀你的意見。

回答

3
  1. 在回答你的一般性問題,「在哪裏處理異常的最好的地方」,答案很簡單:總是處理最接近於它們提出點例外。

    這就是您將掌握處理異常所需信息最多的地方,並且它還會保持代碼依賴關係。如果讓異常冒出太多層次,那麼更高層次的代碼將不得不知道底層代碼的實現細節,這會增加耦合並破壞抽象。

    而這又帶給我們另一個重要的一點:如果你的沒有有足夠的信息可以處理這個異常,或者你不知道該怎麼做,你根本不應該處理這個異常。相反,你應該讓它冒出來,直到它最終到達可以處理它的代碼或失敗的代碼,一個顯示錯誤消息和/或寫入日誌文件和/或向開發者發送轉儲的全局異常處理程序( s),然後優雅地結束應用程序。例外情況不像口袋妖怪;你不應該抓住他們。只抓住你知道如何處理的人。 (Related reading on global exception handling.

  2. 針對您的具體問題,「我怎麼處理情況,文件/記錄/對象未找到的情況下」,答案也相對簡單:總是處理異常

    檢查該對象是否首先存在似乎乍一看是個好主意。這似乎是防禦性編程,而不是試圖做你知道的事情會失敗。我們都知道防禦性編程是一種最佳做法。

    那麼問題是什麼?一個相對微妙的,被稱爲競賽條件。請參閱,僅僅因爲您在嘗試訪問該對象之前確保該對象存在,則該對象可能在您驗證其存在的時間與嘗試訪問它的時間之間消失。在僞代碼中:

    if (!File.Exists(myFile)) 
    { 
        MessageBox("Sorry buddy, that's a no-go."); 
    } 
    else 
    { 
        // Uh-oh! The file got deleted! 
        File.Open(myFile); // fails 
    } 
    

    現在,當然,你可能會對自己說,這聽起來像是非常罕見。在執行兩行代碼之間,對象實際上多久會消失(或者您失去訪問它的能力)?那實際上並不是那麼不可能。考慮文件位於網絡驅動器並且網絡電纜突然拔出的情況。但即使極爲罕見,這就是爲什麼它被稱爲例外:這是一個例外 [盟友罕見]的情況。

    所以這裏的正確解決方案就是處理這個異常,因爲即使你防守編程,你仍需要來處理異常來處理競爭條件。我們都知道不必要的代碼重複是不好的。

1

你會很滿意你的第二個選擇。如果你的代碼中有一些不太可能導致任何異常的部分(如果有的話),那麼你不應該在try-catch中接受它們。
在我看來,只有少數時候只有「單向」來處理異常。有一點很重要,那就是你的代碼中的那些部分會受到警惕,這可能會導致你的程序發生故障甚至崩潰。
此外,使用幾個try-catch塊來捕捉不同的異常也很好。有時候,你有一些例外,你想要平等的特質,而不是進一步區分它們。然而在其他事件中,有一些例外,你根本沒有期望,然後你至少可以使用catch(Exception ex) { ... }

也許在MSDN有點幫助你。