最近項目中,常常碰到這個?和??這兩個操作符,之前說得不夠詳細,趁着周末補全來,希望能夠給大家帶來幫助。
(一)?操作符
我們知道值類型是不肯能為空的,它總是包含值的本身,不會為NULL,這估計也是值類型的由來。 ?應該是為了解決把值類型設置為可空類型而出現的,比如int? y=null這種情況,當數據庫設置某個int類型,datetime類型等等,可以為空的時候,?運算符在我們編程中就會非常有用。其實?這個操作符等價於Nullable<T>。看Nullable<T>的源碼可以了解到如下信息:
namespace System { using System.Runtime.InteropServices; using System.Runtime.Versioning; [Serializable, StructLayout(LayoutKind.Sequential), NonVersionable, __DynamicallyInvokable] public struct Nullable<T> where T : struct { private bool hasValue; //這個類似於一個標注位的作用 internal T value; [NonVersionable, __DynamicallyInvokable] public Nullable(T value) { this.value = value; this.hasValue = true; } [__DynamicallyInvokable] public bool HasValue { [NonVersionable, __DynamicallyInvokable] get { return this.hasValue; } } [__DynamicallyInvokable] public T Value { [__DynamicallyInvokable] get { if (!this.hasValue) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue); } return this.value; } } [NonVersionable, __DynamicallyInvokable] public T GetValueOrDefault() { return this.value; } [NonVersionable, __DynamicallyInvokable] public T GetValueOrDefault(T defaultValue) { if (!this.hasValue) { return defaultValue; //返回默認值。 } return this.value; } [__DynamicallyInvokable] public override bool Equals(object other) { if (!this.hasValue) { return (other == null); } if (other == null) { return false; } return this.value.Equals(other); } [__DynamicallyInvokable] public override int GetHashCode() { if (!this.hasValue) { return 0; } return this.value.GetHashCode(); } [__DynamicallyInvokable] public override string ToString() { if (!this.hasValue) { return ""; } return this.value.ToString(); } [NonVersionable, __DynamicallyInvokable] public static implicit operator T? (T value) { return new T?(value); } [NonVersionable, __DynamicallyInvokable] public static explicit operator T(T? value) { return value.Value; } } }
可以看出該結構表示可以為null的值類型,它本身也是輕量級的,實例是存在棧上的,而且實例大小和原始值類型基本一樣的,只是多了一個Boolean字段。仔細閱讀上面的源碼也可以分析出相關的東西。
(二)?? 空接合操作符
??叫做 null 合並運算符。如果此運算符的左操作數不為 null,則此運算符將返回左操作數;否則返回右操作數。可以用來給變量設置默認值。特別提醒: 記住和空有關的時候,才要去用?? 。如果不會有空的判斷,就別用了。因為這個是空的合並運算符。也有人說??是?:的語法糖而已,但是實際上??進行了很大改進,能夠更好的支持表達式。
(第二種)??在復合情形中,更好用,和上面類似。
還有就是如何把一個條件表達式,用?和??進行合並。
var flag = tt == null ? 1 : tt.Name; 因為這里進行了為Null的判斷,所以可以用??。先寫??。然后再來確定左右兩邊應該寫什么。 var flag= tt?.Name??1 ;這個就是合並后的條件表達式
(三)CLR對可空類型支持
C#設計人員想盡一切方法,讓可空類型,看起來不要那么另類,看起來像一個一等公民。
看了它的Nullable<T>的代碼就知道了,它其實是一個bool類型字段+值類型。其實它很多操作都可以從這里來解釋,裝箱,拆箱。
CLR會說謊----看下圖