簡體   English   中英

.NET CIL Call或CallVirt?

[英].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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM