C# 类型运算符重载在类继承中的调用测试
C# 類型運算符重載在類繼承中的調用測試
這是一篇晦澀難懂的片面的研究?
一,簡單的繼承層次
class CA {}class CB : CA{}class CC : CB{}}void Test(CA oa){//CATestDebug.Log ("CA===============");}void Test(CB oa){//CBTestDebug.Log ("CB===============");}void Test(CC oa){//CCTestDebug.Log ("CC===============");}//測試代碼如下:CC oc = new CC ();Test (oc);在這種情形下調用Test(oc)有如下規律:<通過注釋掉其它函數進行測試>
由此我們得知,Test(oc)調用時,編譯器會由oc的繼承層次由子到父的優先級去匹配重載函數的形參。這也符合正常邏輯。
二,類中有運算符重載的繼承
class CA {}class CB : CA{}class CC : CB{ /* MSDN類型轉換的要求1.操作數必須是封閉類型2.類A到類B的類型轉換定義不能在類C中進行(即2個類的轉換不能在第3個類中定義, 如下面的參數定義)*/public static implicit operator bool(CC ot/*不能是CA ot或 CB ot */){Debug.Log ("bool================");return ot != null;}}void Test(CA oa){//CATestDebug.Log ("CA===============");}void Test(CB oa){//CBTestDebug.Log ("CB===============");}void Test(CC oa){//CCTestDebug.Log ("CC===============");}void Test(bool b){//boolTest
Debug.Log ("b===============")
}
//測試代碼如下:CC oc = new CC ();Test (oc);
此情形下boolTest重載函數和CATest, CBTest, CCTest的任何一個重載都沖突,原因如下:
當調用Test(oc)時,編譯系統將oc與Test的四個重載函數的參數進行匹配,卻發現四個都能匹配成功。Test(bool b)通過CC類的bool類型符重載而匹配。
CATest, CBTest, CCTest三個重載函數由于形參CC,CB,CA是繼承關系,在進行匹配時是有優先級的,由于ot是CC類型的,所以優先級CC>CB>CA,因此這個三個重載函數間沒有沖突,編譯器明確知道該調用哪個重載。而bool重載與CC,CB,CA在類型轉換時是同優先級,因此編譯系統不知道該調用bool重載還是CC,CB,CA的三個重載了。
若將bool重載由類CC移到類CA中,其它代碼不變,測試代碼不變。經測試,boolTest,CATest, CBTest, CCTest四個重載可以共存,即boolTest與其它任何一個重載都不沖突。
這說明了基類的類型重載運算符的調用優先級低于父子層級轉換的優先級,如情形5,在只有bool重載運算符時才會被調用。
本類的類型重載運算符的優先級等于父子層次轉換的優先級。
?三,Unity中的調用
UnityEngine所有類的的基類都是UnityEngine.Object。這個類與System.Object的關系很詭異。
System.Object obj = new UnityEngine.Object()?//這行代碼在編譯上沒問題,其實非常詭異,后面單獨說
這樣寫可以正常編譯。反過來將System.Object賦予UnityEngine.Object則不能編譯通過。
這似乎可以說 System.Object 是 UnityEngine.Object的基類,網上許多人也這么認為。還有人說是隱式繼承。
然而,通過看U3D的API,可以看到UnityEngine.Object并沒有繼承任何類,UnityEngine的源碼中Object也確實沒有繼承任何類。這只能說是CLR內部自己的搞的鬼。
于是在這種情形下,重載函數的調用規律就有了一點小的改變。
這就是:UnityEngine.Object類及子類適用于上面的規律。而System.Object則處于所有類型的最低優先級,低于bool類型轉換重載。例:
public class NewBehaviourScript : MonoBehaviour {void OTest(bool b){//F1 Debug.Log ("OTest--b-");}void OTest(System.Object obj){//F2 Debug.Log ("OTest-system-obj-");}void OTest(UnityEngine.Object obj)//F3 {Debug.Log ("OTest-obj");}void OTest(Transform tran){//F4Debug.Log ("OTest-trans-");}void Start (){OTest (gameObject.transform);}void Update () {} }調用優先級F4>F3>F1>F2。即:
當僅有F1,F2共存時,大多數人的直覺是:OTest (gameObject.transform)肯定會調用F2: OTest(System.Object obj),網上有些同學很早發現了這個詭異現象
附:System.Object obj = new UnityEngine.Object()?這個詭異問題。
可以看到suo?與 uo的調試數據都是 {null},這大概就是表示對象為空吧,if(uo==null)成立,輸出了 uo==null字符串,然而if(suo==null)卻不成立!!對于神奇的.NET,我只能說:用unity時就別用system.Object了。
?
posted on 2016-10-06 18:34 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏
總結
以上是生活随笔為你收集整理的C# 类型运算符重载在类继承中的调用测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 与 Unity 同名函数
- 下一篇: c# char unsigned_dll