Introduction: 在C#6及以上版本中,加入了一項特別好用的運算符:Null條件運算符?.和?[]可以用來方便的執行判空操作,當運算符左側操作數不為null時才會進行訪問操作,否則直接返回null。這極大的簡化的判空代碼的書寫,但在使用過程中仍然需要註意一些問題,以免其帶來我們意想不到的後 ...
Introduction:
在C#6及以上版本中,加入了一項特別好用的運算符:Null條件運算符?.和?[]可以用來方便的執行判空操作,當運算符左側操作數不為null時才會進行訪問操作,否則直接返回null。這極大的簡化的判空代碼的書寫,但在使用過程中仍然需要註意一些問題,以免其帶來我們意想不到的後果。
例如博主在使用Unity游戲引擎時便遇到使用下麵代碼依然會拋出空引用異常的情況:
using UnityEngine; public class MyMonoBehaviour : MonoBehaviour { public MyMonoBehaviour myMonoBehaviour; public void Start() { this.myMonoBehaviour?.Foo(); } public void Foo() { Debug.Log(this.gameObject.name); } }
為什麼使用了Null條件運算符還會出現空引用異常的情況,這需要從.Net編譯器對該運算符的實現說起。
Body:
查看以上代碼中Start()函數的IL代碼:
可以發現在IL_0008中會判斷欄位myMonoBehaviour是否為空,如果非空,則跳轉到IL_000d執行調用實例方法Foo(),否則跳轉到IL_0013行返回。這裡的判空只是進行按位來判斷是否為空,然而在Unity游戲引擎中,MonoBehaviour繼承自UnityEngine.Object,其重寫了==和!=運算符,因此按位執行判空操作顯然是無法滿足要求的,當其引用的物體被銷毀而該引用依然保存的時候,就會在調用gameObject屬性時拋出異常。
此時,使用正常的判空操作則會避免這個問題:
public void OnEnable() { if (this.myMonoBehaviour != null) { this.myMonoBehaviour?.Foo(); } }
Conclusion:
因此,在使用Null條件運算符時,需要特別註意操作數所指向對象的運行時類型是否重寫了==和!=運算符,如果重寫了這些運算符,那麼就儘量不能使用Null條件運算符,而應該使用傳統的判空方式。
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的認可是我寫作的最大動力!
作者:Minotauros
出處:https://www.cnblogs.com/minotauros/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。