当前位置:网站首页>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值类型的需求,一方面提高了代码的简练性。因此其实可以在写代码的时候适当的习惯使用。
边栏推荐
- [optimal web page width and its implementation] [recommended collection "
- 漏电继电器LLJ-100FS
- 不同网段之间实现GDB远程调试功能
- [JS component] date display.
- 漏电继电器JELR-250FG
- Digital innovation driven guide
- Torch optimizer small parsing
- Egr-20uscm ground fault relay
- Cve-2021-3156 vulnerability recurrence notes
- Where is NPDP product manager certification sacred?
猜你喜欢

LabVIEW is opening a new reference, indicating that the memory is full

Torch optimizer small parsing

Is the human body sensor easy to use? How to use it? Which do you buy between aqara green rice and Xiaomi

Annotation初体验

JVM (19) -- bytecode and class loading (4) -- talk about class loader again

Leakage relay jd1-100

1.AVL树:左右旋-bite

5. 数据访问 - EntityFramework集成

Dj-zbs2 leakage relay

Leetcode (417) -- Pacific Atlantic current problem
随机推荐
高压漏电继电器BLD-20
4. Object mapping Mapster
“多模态”概念
一条 update 语句的生命经历
JVM (XX) -- performance monitoring and tuning (I) -- Overview
Senior programmers must know and master. This article explains in detail the principle of MySQL master-slave synchronization, and recommends collecting
1.AVL树:左右旋-bite
Use, configuration and points for attention of network layer protocol (taking QoS as an example) when using OPNET for network simulation
【oracle】简单的日期时间的格式化与排序问题
Life experience of an update statement
Codeforces Round #416 (Div. 2) D. Vladik and Favorite Game
[reading of the paper] a multi branch hybrid transformer network for channel terminal cell segmentation
阿里云的神龙架构是怎么工作的 | 科普图解
张平安:加快云上数字创新,共建产业智慧生态
AIDL 与Service
ThinkPHP Association preload with
Zhang Ping'an: accelerate cloud digital innovation and jointly build an industrial smart ecosystem
LabVIEW is opening a new reference, indicating that the memory is full
Tencent cloud database public cloud market ranks top 2!
The year of the tiger is coming. Come and make a wish. I heard that the wish will come true