国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

可空類型為什么可以為空?也許會被面試到哦。。。

2019-11-14 16:35:16
字體:
來源:轉載
供稿:網友

 

  也許某天你來某一家公司面試,或許就會被問到這個問題,當你看到這個問題,也許會立即反編譯下源代碼看個究竟。

  1 [Serializable, StructLayout(LayoutKind.Sequential), __DynamicallyInvokable]  2 public struct Nullable<T> where T: struct  3 {  4     PRivate bool hasValue;  5     internal T value;  6     [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable]  7     public Nullable(T value)  8     {  9         this.value = value; 10         this.hasValue = true; 11     } 12  13     [__DynamicallyInvokable] 14     public bool HasValue 15     { 16         [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 17         get 18         { 19             return this.hasValue; 20         } 21     } 22     [__DynamicallyInvokable] 23     public T Value 24     { 25         [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 26         get 27         { 28             if (!this.HasValue) 29             { 30                 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue); 31             } 32             return this.value; 33         } 34     } 35     [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 36     public T GetValueOrDefault() 37     { 38         return this.value; 39     } 40  41     [__DynamicallyInvokable] 42     public T GetValueOrDefault(T defaultValue) 43     { 44         if (!this.HasValue) 45         { 46             return defaultValue; 47         } 48         return this.value; 49     } 50  51     [__DynamicallyInvokable] 52     public override bool Equals(object other) 53     { 54         if (!this.HasValue) 55         { 56             return (other == null); 57         } 58         if (other == null) 59         { 60             return false; 61         } 62         return this.value.Equals(other); 63     } 64  65     [__DynamicallyInvokable] 66     public override int GetHashCode() 67     { 68         if (!this.HasValue) 69         { 70             return 0; 71         } 72         return this.value.GetHashCode(); 73     } 74  75     [__DynamicallyInvokable] 76     public override string ToString() 77     { 78         if (!this.HasValue) 79         { 80             return ""; 81         } 82         return this.value.ToString(); 83     } 84  85     [__DynamicallyInvokable] 86     public static implicit operator T?(T value) 87     { 88         return new T?(value); 89     } 90  91     [__DynamicallyInvokable] 92     public static explicit operator T(T? value) 93     { 94         return value.Value; 95     } 96 } 97  98   99 Collapse Methods100  

 

當你reflector之后,你可能會快速的認為這個就是答案,但是你真的把這個代碼拷貝到編輯器中,你會發現如下的錯誤。

 

從圖中可以看到,原來事情沒有這么簡單,最后還是回到了原來的問題上,null不能給值類型賦值,這個時候,你可能就比較好奇。

我們的FCL中定義的類怎么就能逃過編譯器呢?

 

①:我們用ILdasm看下il代碼。

1     class Program2     {3         static void Main(string[] args)4         {5             Nullable<Int32> i = null;6         }7     }

 

②:下面我們再將Nullable<Int32> i = null 改成 Nullable<Int32> i = 0,看看il代碼是怎么樣的。

1     class Program2     {3         static void Main(string[] args)4         {5             Nullable<Int32> i = 0;6         }7     }

 

下面我們比較比較這兩張圖不一樣的地方。

《1》 當 Nullable<Int32> i = 0 的時候,發現Nullable被實例化了(instance),并且還調用了其構造函數(ctor(!0)),

這種情況我們看Nullable的結構體定義,發現是非常合乎情理的。

 

《2》當 Nullable<Int32> i = null 的時候,從IL代碼上看,只是調用了initobj指令,并沒有實例化,也沒有調用構造函數,

再看看這個指令的意思:將位于指定地址的對象的所有字段初始化為空引用或適當的基元類型的 0。

①:既然是”初始化“操作,那我應該也可以寫成這樣:

1     class Program2     {3         static void Main(string[] args)4         {5             Nullable<Int32> i = new Nullable<Int32>();6         }7     }

 

②:既然是“初始化”,那么作為null的Nullable應該可以調用實例方法并不報錯,這就如指令說的一樣,如果成功,那就

說明null只是Nullable的一種狀態,不能跟“類”中的空引用混淆。

     從上面的三張圖上可以看出,也許答案就在這個里面,編譯器和CLR作為“特等公民”在底層做了很多我們看不到的東西,

這其中就像上圖一樣給我們多加了一種”可空狀態“,只是如何做的,我們看不到而已。

 

《3》既然說到null,我也很好奇的看看到底“類”下面的null是什么情況。

1     class Program2     {3         static void Main(string[] args)4         {5             Program p = null;6         }7     }

 

ldnull的意思是:將空引用推送到計算堆棧上。

可以看到,既然沒有new,也就不會在堆中分配內存,而這里是將null放入到線程棧中,不知道編譯器在initobj中

是否也有類似的操作。。。

 

最后要說的是:希望大家討論討論,畢竟我也是猜測而已,并沒有實實在在的看到那些給我們隱藏的東西。

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 丘北县| 齐齐哈尔市| 顺平县| 乌兰浩特市| 黄梅县| 台中县| 杂多县| 新巴尔虎右旗| 武定县| 时尚| 福泉市| 凤城市| 沂南县| 黄陵县| 龙南县| 南昌市| 林甸县| 武汉市| 海兴县| 南雄市| 平乡县| 仁寿县| 彭泽县| 华蓥市| 牟定县| 曲水县| 长宁区| 宁海县| 潢川县| 安庆市| 信阳市| 南皮县| 大余县| 霍邱县| 绍兴市| 玛沁县| 建阳市| 常宁市| 刚察县| 柯坪县| 阳原县|