最近项目中,常常碰到这个?和??这两个操作符,之前说得不够详细,趁着周末补全来,希望能够给大家带来帮助。
(一)?操作符
我们知道值类型是不肯能为空的,它总是包含值的本身,不会为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会说谎----看下图