建議3 區別對待強制轉型與as和is

2021-07-22 05:06:36 字數 2845 閱讀 7181

建議3: 區別對待強制轉型與as和is

在闡述本建議之前,首先需要明確什麼是強制轉型,以及強制轉型意味著什麼。從語法結構上來看,類似下面的**就是強制轉型。

secondtype = (secondtype)firsttype; 

但是,強制轉型可能意味著兩件不同的事情:

1)firsttype和secondtype彼此依靠轉換操作符來完成兩個型別之間的轉型。

2)firsttype是secondtype的基類。

型別之間如果存在強制轉型,那麼它們之間的關係,要麼是第一種,要麼是第二種,不能同時既是繼承的關係,又提供了轉型符。

首先看第一種情況,當firsttype和secondtype存在轉換操作符時的**如下:

class

firsttype

} class

secondtype

public

static

explicit

operator

secondtype(firsttype firsttype)

; return

secondtype;

} }

在這種情況下,如果想轉型成功則必須使用強制轉型,而不是使用as操作符。

firsttype firsttype = new firsttype() ;  

secondtype secondtype = (secondtype)firsttype; //

轉型成功

//secondtype = firsttype as secondtype;

//編譯期轉型失敗,編譯通不過

不過,這裡需要討論的不是像以上**這樣的簡單應用,而是稍微複雜一點的應用。為了滿足更進一步的需求,我們需要寫乙個通用的方法,需要對firsttype或者secondtype做一些處理,方法看起來應該像下面這樣:

static

void dowithsometype(object

obj)

注意 是否對這種方法宣告方式有一點熟悉?事實上,如果再加乙個引數eventargs,上面的方法就可以註冊成為乙個典型的clr事件方法了。

如果執行本段**,會帶來乙個問題:若在呼叫方法的時候,傳入的引數是乙個firsttype物件,那就會引發異常。你可能會問,在上一段**中,有這樣的寫法:

firsttype firsttype = new firsttype() ;  

secondtype secondtype = (secondtype)firsttype;

而dowithsometype方法提供的**,看起來無非像下面這樣:

firsttype firsttype = new firsttype() ;  

object obj =firsttype;

secondtype secondtype = (secondtype) obj;

也就是說,這段**與上段**相比,僅僅多了一層轉型,實際上obj還是firsttype,為什麼轉型就失敗了呢?這是因為編譯器還不夠聰明,或 者說我們欺騙了編譯器。針對(secondtype) obj,編譯器首先判斷的是:secondtype和object之間有沒有繼承關係。因為在c#中,所有的型別都是繼承自object的,所以上面的代 碼編譯起來肯定沒有問題。但是編譯器會自動產生**來檢查obj在執行時是不是secondtype,這樣就繞過了轉換操作符,所以會轉換失敗。因此,這 裡的建議是:

如果型別之間都上溯到了某個共同的基類,那麼根據此基類進行的轉型(即基類轉型為子類本身)應該使用as。子類與子類之間的轉型,則應該提供轉換操作符,以便進行強制轉型。

注意 再次強調,轉型操作符實際上就是乙個方法,型別的轉換需要手工寫**完成。

為了編寫更健壯的dowithsometype方法,應該按如下方式改造它:

static

void dowithsometype(object

obj)

}

as操作符永遠不會丟擲異常,如果型別不匹配(被轉換物件的執行時型別既不是所轉換的目標型別,也不是其派生型別),或者轉型的源物件為null, 那麼轉型之後的值也為null。改造前的dowithsometype方法會因為引發異常帶來效率問題,而使用as後,就可以完美地避免這種問題。

現在,再來看第二種情況,即firsttype是secondtype的基類。在這種情況下,既可以使用強制轉型,也可以使用as操作符,**如下所示:

class

program

; firsttype firsttype1 =(firsttype)secondtype;

firsttype firsttype2 = secondtype as

firsttype;

} }

class

firsttype

} class

secondtype : firsttype

但是,即使可以使用強制轉型,從效率的角度來看,也建議大家使用as操作符。

知道了強制轉型和as之間的區別,我們再來看一下is操作符。dowithsometype的另乙個版本,可以這樣來實現,**如下所示:

static

void dowithsometype(object

obj)

}

這個版本顯然沒有上乙個版本的效率高,因為當前這個版本進行了兩次型別檢測。但是,as操作符有乙個問題,即它不能操作基元型別。如果涉及基元型別的演算法,就需要通過is轉型前的型別來進行判斷,以避免轉型失敗。

**:《編寫高質量**改善c#程式的157個建議》陸敏技

建議6 區別readonly和const的使用方法

區別 const是乙個編譯期常量,readonly是乙個執行時常量。const只能修飾基元型別,列舉型別和字串型別,readonly沒有限制。const變數的效率高,是因為經過編譯器編譯後,我們在 中引用const變數的地方都會用const變數所對應的實際值來代替 const int constva...

建議6 區別readonly和const的使用方法

很多初學者分不清這兩者的使用場合。在我看來,要使用const的理由只有乙個,那就是效率。但是,大部分情況下,效率並沒有那麼高的地位,所以我更願意採用readonly,因為readonly賦予 更多的靈活性。它們的本質區別如下 1 const是應該編譯期常量,readonly是乙個執行時常量。2 co...

SVN與GIT區別對比

1 svn優缺點 優點 1 管理方便,邏輯明確,符合一般人思維習慣。2 易於管理,集中式伺服器更能保證安全性。3 一致性非常高。4 適合開發人數不多的專案開發。缺點 1 伺服器壓力太大,資料庫容量暴增。2 如果不能連線到伺服器上,基本上不可以工作,看上面第二步,如果伺服器不能連線上,就不能提交,還原...