[英].NET CIL Call or CallVirt?
如何確定是否需要使用“Call”或“Callvirt”調用方法?
默認情況下,C#編譯器始終將callvirt用於除靜態或值類型調用之外的所有內容。 這會導致對'this'(arg0)參數進行隱式空值檢查。 您並不是嚴格要求遵循此約定,但引用類型上的任何虛擬方法肯定都需要callvirt。
您可以逐個遵循這些簡單的規則來確定您應該使用哪些:
static
嗎? 然后使用call
。 call
。 (如果值被裝箱,則不適用 - 那么您實際上是在object
或某個界面上調用,而這些是引用類型。) virtual
還是abstract
? 然后使用callvirt
。 callvirt
。 override
,但方法和聲明類型都沒有聲明sealed
? 然后使用callvirt
。 在所有其他情況下,不需要虛擬調度,因此您可以使用call
- 但您應該使用callvirt
。 原因如下:
在非虛方法上使用callvirt
等同於call
除非第一個參數為null。 在這種情況下, callvirt
會立即拋出NullReferenceException
,而call
則不會。 這是有道理的,因為callvirt
旨在用於需要虛擬方法調度的情況,如果沒有可以進行vtable查找的對象,則無法進行虛擬方法調度。
請注意,即使不需要vtable查找,如果第一個參數為null, callvirt
仍將拋出異常!
考慮到這一信息,使用callvirt
對引用類型的所有非靜態方法調用(如C#編譯器)可以是優選的,因為它會導致NullReferenceException
,立即在調用點,而不是一段時間后,當this
被使用(明確或隱含)方法內部。
如果在虛方法的dynamic方法中使用call,則運行時會拋出安全異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.