小酌重構系列[20]——用條件判斷代替異常

概述

異常處理的關鍵在於什麼時候處理異常以及如何使用異常,有些開發者會以爲try catch的處理和使用難以把握,因而他們秉承着「您可錯殺一千,不可放過一個」的想法,給全部的方法添加try catch。html

這種方式會對應用程序形成什麼影響嗎?程序員

從用戶角度出發,用戶確實難以察覺到什麼,應用程序運行正常,使用的體驗好像也沒什麼差異。性能

從程序角度出發,大量的try catch會下降代碼的可讀性,只有在異常觸發時纔會對程序的性能形成較大的影響。設計

這兩種角度有對錯嗎?htm

兩者都沒有錯,第一種角度甚至要遠遠高於第二種角度。對象

對於程序員來講,寫程序開發產品的最終目的不是爲了在技術上吹毛求疵,而是爲了知足市場和用戶的業務需求,用戶並不關心產品的內部實現——用戶以爲好的產品,是真正的好產品。blog

咱們沒必要糾結於這兩種角度的處理方式,適合本身的纔是最佳的。開發

可是一些場景下確實不宜使用try catchget

  1. 流程控制語句:流程控制有它自己的邏輯,咱們應該用判斷來規避try catch語句塊的使用
  2. 循環控制語句:一次catch對性能的影響是較小的,但在循環中卻能夠聚沙成塔,所以可能會產生較大的性能損失。

本文的主題「用條件判斷代替異常」是針對場景1的,當使用try catch來控制程序流程時,若是程序中不存在「危險」代碼(例如:類型轉換、創建鏈接等),就沒有必要使用try catch,咱們能夠直接使用條件判斷來控制程序流程。產品

異常不發生的時候,只是給程序套了一層try{}語句塊,對性能的影響微乎其微。
當異常發生的時候,進入catch語句塊,CLR須要建立異常對象,保存堆棧信息,逐層查找異常表,這會較大地影響程序的性能。

異常處理是一個較大的課題,也是程序設計的一個橫切關注點,本文不會對此進行深刻的說明。

示例

重構前

下面這段代碼表示「微波爐當前若是沒有被使用,那麼咱們就能夠用它加熱食物」。

public class Microwave
{
    private IMicrowaveMotor Motor { get; set; }

    public bool Start(object food)
    {
        bool foodCooked = false;
        try
        {
            Motor.Cook(food);
            foodCooked = true;
        }
        catch (InUseException)
        {
            foodcooked = false;
        }

        return foodCooked;
    }
}

這段代碼經過是否觸發自定義異常InUseException,來決定方法Start()方法的返回值,這是典型的使用try catch語句塊來控制流程的作法。

catch語句塊捕獲了InUseException,卻沒有處理InUseException,這不只損失了程序的性能,也未體現自定義異常InUseException的價值。
這僅僅是一個常見的邏輯判斷,咱們用條件判斷就能夠了。

重構後

重構之後,代碼的可讀性加強了,還消除了捕捉異常帶來的性能損失。

public class Microwave
{
    private IMicrowaveMotor Motor { get; set; }

    public bool Start(object food)
    {
        if (Motor.IsInUse)
            return false;

        Motor.Cook(food);

        return true;
    }
}
相關文章
相關標籤/搜索