当前位置:网站首页>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值类型的需求,一方面提高了代码的简练性。因此其实可以在写代码的时候适当的习惯使用。
边栏推荐
猜你喜欢
Egr-20uscm ground fault relay
不同网段之间实现GDB远程调试功能
Paper reading [MM21 pre training for video understanding challenge:video captioning with pre training techniqu]
sql优化常用技巧及理解
论文阅读【Open-book Video Captioning with Retrieve-Copy-Generate Network】
4. 对象映射 - Mapping.Mapster
Is the human body sensor easy to use? How to use it? Which do you buy between aqara green rice and Xiaomi
Leetcode: maximum number of "balloons"
EGR-20USCM接地故障继电器
The year of the tiger is coming. Come and make a wish. I heard that the wish will come true
随机推荐
1. AVL tree: left-right rotation -bite
Make web content editable
张平安:加快云上数字创新,共建产业智慧生态
京东商品详情页API接口、京东商品销量API接口、京东商品列表API接口、京东APP详情API接口、京东详情API接口,京东SKU信息接口
Paper reading [MM21 pre training for video understanding challenge:video captioning with pre training techniqu]
How digitalization affects workflow automation
Zhang Ping'an: accelerate cloud digital innovation and jointly build an industrial smart ecosystem
《4》 Form
论文阅读【Semantic Tag Augmented XlanV Model for Video Captioning】
漏电继电器JELR-250FG
Leakage relay jelr-250fg
4. Object mapping Mapster
Annotation初体验
High voltage leakage relay bld-20
Phenomenon analysis when Autowired annotation is used for list
np. random. Shuffle and np Use swapaxis or transfer with caution
消息队列:重复消息如何处理?
高级程序员必知必会,一文详解MySQL主从同步原理,推荐收藏
导航栏根据路由变换颜色
利用OPNET进行网络任意源组播(ASM)仿真的设计、配置及注意点