当前位置:网站首页>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
- Pinduoduo product details interface, pinduoduo product basic information, pinduoduo product attribute interface
- If you want to choose some departments to give priority to OKR, how should you choose pilot departments?
- How can project managers counter attack with NPDP certificates? Look here
- 利用OPNET进行网络指定源组播(SSM)仿真的设计、配置及注意点
- [question] Compilation Principle
- JVM (19) -- bytecode and class loading (4) -- talk about class loader again
- 消息队列:重复消息如何处理?
- 1. AVL tree: left-right rotation -bite
- Wonderful express | Tencent cloud database June issue
猜你喜欢
不同网段之间实现GDB远程调试功能
基于NCF的多模块协同实例
K6EL-100漏电继电器
ssm框架的简单案例
CentOS 7.9 installing Oracle 21C Adventures
Design, configuration and points for attention of network specified source multicast (SSM) simulation using OPNET
Photo selector collectionview
Egr-20uscm ground fault relay
How digitalization affects workflow automation
【js组件】date日期显示。
随机推荐
Vector and class copy constructors
[论文阅读] A Multi-branch Hybrid Transformer Network for Corneal Endothelial Cell Segmentation
Jhok-zbg2 leakage relay
ssm框架的简单案例
设f(x)=∑x^n/n^2,证明f(x)+f(1-x)+lnxln(1-x)=∑1/n^2
Most commonly used high number formula
【js组件】date日期显示。
[binary tree] binary tree path finding
JSP setting header information export to excel
Codeforces Round #416 (Div. 2) D. Vladik and Favorite Game
Jhok-zbl1 leakage relay
1.AVL树:左右旋-bite
JHOK-ZBG2漏电继电器
利用OPNET进行网络单播(一服务器多客户端)仿真的设计、配置及注意点
Educational Codeforces Round 22 B. The Golden Age
【oracle】简单的日期时间的格式化与排序问题
How can project managers counter attack with NPDP certificates? Look here
消息队列:如何确保消息不会丢失
利用OPNET进行网络仿真时网络层协议(以QoS为例)的使用、配置及注意点
Record a pressure measurement experience summary