《CLR Via C#》学习笔记系列06---C# 可空值类型
我们知道,值类型的变量永远不会为null,但在数据库中的一个列可能允许值为空,但在CLR中没有办法将INT32值表示成null.
为了解决这个问题,CLR中引入了可空值类型,为了理解它是如何工作的,先来看看FCL中定义的system.Nullable<T>结构。
一、可空值类型的代码
public struct Nullable<T> where T : struct { //两个字段表示状态 private Boolean hasValue = false; //假定null internal T value = default(T);//假定所有位都为O public Nullable(T value) { this.value = value; this.hasValue = true; } public Boolean HasValue { get { return hasValue; } } public T Value { get { if (!hasValue) { throw new InvalidOperationException("可空对象必须有值。"); } return value; } } public T GetValueOrDefault() { return value; } public T GetValueOrDefault(T defaultValue) { if (!hasValue) return defaultValue; return value; } //重载equals方法 public override bool Equals(object obj) { if (!HasValue) return (obj == null); if (obj == null) return false; return value.Equals(obj); } //重载toString()方法 public override string ToString() { if (!HasValue) return ""; return value.ToString(); } public static implicit operator Nullable<T>(T value) { return new Nullable<T>(value); } public static explicit operator T(Nullable<T> value) { return value.Value; } }
可以看出,可空类型是一个结构类型,也就是说本身是一个值类型,实例仍然是在栈上,Nullable的类型参数被约束为struct,也就是说这个类型是为了值类型而设定的。
二、可空值类型的使用
我们要在代码中使用一个可空的Int32,就可以像下面这样写:
Nullable<Int32> x = 5; Nullable<Int32> x = null;
但是在C#中一般是这样写
int? x = 5; int? x = null;
三、合并操作符
C# 提供了一个空接合操作符,即??操作符,假如左边的不为null,就返回这个操作数,如果左边的为null,就返回右边的操作数。
下面两行代码是等价的
int? b = null; int a = (b.HasValue) ? b.Value : 123; int a = b ?? 123;
四、可空类型的装箱和拆箱
装箱:当CLR对可空类型进行装箱时,会检查它是否为NULL,如果是,CLR不装箱任何东西,直接返回NULL,如果可空实例不为NULL,CLR从可空实例中取出值并进行装箱,也就是说,值为5的可空类型会装箱成值为5的已装箱INT32.
拆箱:如果已装箱的值类型引用的是NULL,要把它拆箱成可空类型,那么CLR会将可空类型的值设为NULL.
五、可空类型调用GetType
在可空类型上调用GetType,实际会撒谎说类型是T,而不是Nullable<T>。也就是说 Int32? x=5 ;在执行 x.GetType()时,会显示System.Int32, 而不是System.Nullable<Int32>;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!