当前位置:网站首页>C#可空类型
C#可空类型
2022-07-06 23:41:00 【bommy游戏】
一、为什么需要可空类型
- 我们都知道数据库里的数值型字段都是可空的,比如某个Int字段,它可以有值也可以没有值,我们要把这个字段读取出来保存在一个Int类型变量里,就必须考虑到它没有值的情形。这个时候,就需要借助可空类型来实现了。
- 下面是一个例子: Java 的 java.util.Date 类是引用类型,所以该类型的变量能设为null,但是CLR的System.DateTime 定值类型,DateTime 变量永远不能设为 null 。如果用 Java 写的应用程序想和运行 CLR 的 Web 服务交流日期/时间,那么一旦 Jaya 程序发送 null酒会出问题,因为 CLR 不知道如何表示 nul ,也不知道如何操作它。
- 经常出现有时候我们开发的时候,希望没有初始化一个值与初始化作区分,之前的做法是约定一个很特别的值,然后判断是不是相等来决定要不要赋值。
二、System.Nullable< T >源码
先展示一下源码:
源码地址:https://referencesource.microsoft.com/#mscorlib/system/nullable.cs,ffebe438fd9cbf0e
public struct Nullable<T> where T : struct
{
private bool hasValue;
internal T value;
[System.Runtime.Versioning.NonVersionable]
public Nullable(T value) {
this.value = value;
this.hasValue = true;
}
public bool HasValue {
[System.Runtime.Versioning.NonVersionable]
get {
return hasValue;
}
}
public T Value {
get {
if (!hasValue) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
}
return value;
}
}
[System.Runtime.Versioning.NonVersionable]
public T GetValueOrDefault() {
return value;
}
[System.Runtime.Versioning.NonVersionable]
public T GetValueOrDefault(T defaultValue) {
return hasValue ? value : defaultValue;
}
public override bool Equals(object other) {
if (!hasValue) return other == null;
if (other == null) return false;
return value.Equals(other);
}
public override int GetHashCode() {
return hasValue ? value.GetHashCode() : 0;
}
public override string ToString() {
return hasValue ? value.ToString() : "";
}
[System.Runtime.Versioning.NonVersionable]
public static implicit operator Nullable<T>(T value) {
return new Nullable<T>(value);
}
[System.Runtime.Versioning.NonVersionable]
public static explicit operator T(Nullable<T> value) {
return value.Value;
}
}
根据上面代码,可以看到 Nullable模板也是一个结构体,值类型,也是轻量级的。只不过增加了一个bool hasValue,这个值在构造结构体的时候设置为true。之后如果获取value的话,如果没构造,就会抛出异常。
因此,在代码中构造一个可空的int,可以写:
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
Nullable<int> x = 5;
Nullable<int> y = null;
Console.WriteLine($"x hasvalue : {x.HasValue} Value: {x.Value}");
Console.WriteLine($"y hasvalue : {y.HasValue} Value: {y.GetValueOrDefault()}");
}
}
}
结果如下:
三、c#对可空类型的支持
虽然声明一个Nullable模板可以做到可空类型,但是官方还是觉得写起来麻烦,所以c# 2.0以后就在语言层面添加了对可空类型的支持。
C#允许使用?表示法来声明:
int? x1 = 5;
int? y1 = null;
在c#中 int? 就等于 Nullable< T >
允许向可空实例应用操作符:
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
int? x = 5;
int? y = null;
//一元
x++;
y = -y;
//二元
x += 3;
y += 3;
//相等性
if (x == y)
{
}
//比较
if (x < y)
{
}
}
}
}
所有运算中,只要一个值为null 那么结果就是null
三、c#的空接合操作符
c#土工了一个“空接合操作符( null - coalescing operator ),即??操作符,它要获取两个操作数。假如左边的操作数不为 nul ,就返回这个操作数的值。如果左边的操作数为 null ,就返回右边的操作数的值。利用空接合操作符,可以方便地设置变量的默认值。
空接操作符的一个好处在于,它既能用于引用类型,也能用于可空值类型。以下代码演示了如何使用??操作符:
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
int? x = null;
int? y = x.HasValue ? x : 123;
int? z = x ?? 123;
}
}
}
上面代码中,z的初始化,等价于y的初始化,但是更简便。
四、可空类型的装箱拆箱:
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
int? x = null;
object o = x;
Console.WriteLine($"o is null ? {o == null}");
x = 5;
o = x;
Console.WriteLine($"o is null ? {o == null}");
}
}
}
从上面结果可以看到装箱的时候需要看可空类型是不是为null,如果为空不会发生装箱操作,object仍让是null。
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
object o = 5;
int? x = (int?)o; // 5
int y = (int)o; // 5
Console.WriteLine($"x: {x.Value} y {y}");
o = null;
int? x1 = (int?)o; // null
int y1 = (int)o; //System.NullReferenceException:“Object reference not set to an instance of an object.”
Console.WriteLine($"x1: {x1.Value} y1 {y1}");
}
}
}
从上面代码可以看出来,拆箱对于非null对象可以转成 int 或者 int?,但是对于null对象,如果转成int则会抛出异常。
五、可空类型的GetType()
在Nullable< T >对象上调用GetType()方法,CLR实际上会撒谎说类型是T,而不是Nullable< T >。
因此运行如下代码:
int? x = 5;
Console.WriteLine($"x.GetType() : {x.GetType()}");
结果:
总结
可空类型,一方面兼容了一些业务对null值类型的需求,一方面提高了代码的简练性。因此其实可以在写代码的时候适当的习惯使用。
边栏推荐
- Digital innovation driven guide
- 基于NCF的多模块协同实例
- K6el-100 leakage relay
- 1.AVL树:左右旋-bite
- 消息队列:重复消息如何处理?
- Design, configuration and points for attention of network arbitrary source multicast (ASM) simulation using OPNET
- Paper reading [open book video captioning with retrieve copy generate network]
- Mysql database learning (7) -- a brief introduction to pymysql
- 【oracle】简单的日期时间的格式化与排序问题
- [JS component] custom select
猜你喜欢
sql优化常用技巧及理解
Pinduoduo product details interface, pinduoduo product basic information, pinduoduo product attribute interface
Use Zhiyun reader to translate statistical genetics books
论文阅读【Semantic Tag Augmented XlanV Model for Video Captioning】
LabVIEW is opening a new reference, indicating that the memory is full
CentOS 7.9 installing Oracle 21C Adventures
Getting started with DES encryption
Digital innovation driven guide
How Alibaba cloud's DPCA architecture works | popular science diagram
漏电继电器JD1-100
随机推荐
LabVIEW is opening a new reference, indicating that the memory is full
什么是依赖注入(DI)
Educational Codeforces Round 22 B. The Golden Age
JD commodity details page API interface, JD commodity sales API interface, JD commodity list API interface, JD app details API interface, JD details API interface, JD SKU information interface
漏电继电器LLJ-100FS
Zero sequence aperture of leakage relay jolx-gs62 Φ one hundred
Unity让摄像机一直跟随在玩家后上方
nodejs获取客户端ip
删除文件时提示‘源文件名长度大于系统支持的长度’无法删除解决办法
Pinduoduo product details interface, pinduoduo product basic information, pinduoduo product attribute interface
做自媒体,有哪些免费下载视频剪辑素材的网站?
[JS component] custom select
淘宝店铺发布API接口(新),淘宝oAuth2.0店铺商品API接口,淘宝商品发布API接口,淘宝商品上架API接口,一整套发布上架店铺接口对接分享
漏电继电器JD1-100
How can project managers counter attack with NPDP certificates? Look here
Vector and class copy constructors
利用OPNET进行网络任意源组播(ASM)仿真的设计、配置及注意点
Design, configuration and points for attention of network specified source multicast (SSM) simulation using OPNET
[optimal web page width and its implementation] [recommended collection "
How digitalization affects workflow automation