【.NET Core】可为null类型详解

【.NET Core】可为null类型详解

文章目录

  • 【.NET Core】可为null类型详解
    • 一、概述
    • 二、可为空的值类型
      • 2.1 声明和赋值
      • 2.2 检查可为空值类型
      • 2.3 基础类型与可为空的值类型互换
      • 2.4 可为空的值类型装箱和取消装箱
      • 2.5 如何确定可为空的值类型
    • 三、可为 null 的引用类型

在这里插入图片描述

一、概述

null关键字是表示不引用任何对象的空引用的文字值。null是引用类型变量的默认值。普通值类型不能为null,可为空的值类型除外

二、可为空的值类型

可为null值类型T?表示其基础值类型T的所有值及额外的null值。基础值类型T本身不能是可为空的值类型。

任何可为空的值类型都是泛型System.Nullable<T>结构的实例。可使用以下任何一种互换形式引用具有基础类型T的可为空值类型:Nullable<T>T?

需要表示基础类型的未定义值时,通常使用可为空的值类型。如:布尔值或bool变量只能为truefalse。但是,在某些应用程序中,变量值可能未定义或缺失。在这种情况下可以使用bool?类型。

2.1 声明和赋值

由于值类型可隐式转换为相应的可为空的值类型,因此可以像其基础类型赋值一样,向可为空值类型的变量赋值,还可以分配null值。具体实例如下:

double? pi=3.1415926;
char? letter='c';
int a=110;
int? ab=a;
bool? flag =null;
int?[] arr= new int?[8];

可为空值类型的默认值表示null,也就是说,它是其Nullable<T>.HasValue属性返回false的实例。

2.2 检查可为空值类型

可将is运算符与类型模式结合使用,既检查null的可为空值类型的实例,又检索基础类型的值:

int? a = 42;
if(a is int valueOfA){Console.WriteLine($"a is {valueOfA}");  
}else{Console.WriteLine("a does not have a value.");   
}

始终可以使用以下只读属性来检查和获取可为空值类型变量的值:

  • Nullable<T>.HasValue指示可为空值类型的实例是否有基础类型的值。
  • 如果HasValuetrue,则Nullable<T>.Value获取基础类型的值。如果HasValuefalse,则Value属性将引发IvalidOperationException

使用HasValue属性在显示值之前测试变量是否包含该值:

int? b=10;
if(b.HasValue)
{Console.WriteLine($"b is {b.Value}");
}else{Console.WirteLine("b does not have a value.");
}

还可以通过可为空类型与null进行比较,如:

int? bc = 7;
if (bc != null)
{Console.WriteLine($"c is {c.Value}");
}
else
{Console.WriteLine("c does not have a value");
}

2.3 基础类型与可为空的值类型互换

如果要将可为空值类型的值分配给不可以为null的值类型变量,则可能需要指定要分配的替代null的值。使用Null和并操作符??执行此操作(也可将Nullable<T>.GetValueOrDefault(T)方法用于相同的目的):

int? pi=3.14;
int b = pi??-1;
Console.WriteLine($"b is {b}");
int? c=null;
int d =c??-1;
Console.WriteLine($"d is {d}");

如果要使用基础值类型的默认值为null,需要使用Nullable<T>.GetValueOrDefault()方法。

还可以将可为空的值类型显示强制转换为不可为null的类型。如下:

int? n = null;
int n2 = (int)n;

在运行时,如果可为空的值类型的值为 null,则显式强制转换将抛出InvalidOperationException。不可为null的值类型T隐式转换为相应的可为空值类型T?

2.4 可为空的值类型装箱和取消装箱

可为空值类型的实例T?已装箱;

  • 如果HasValue返回false,则生成空引用。
  • 如果HasValue返回true,则基础值类型T的对应值将将装箱,而不对Nullable<T>的实例进行装箱。

可将值类型T的已装箱值取消装箱到相应的可为空值类型T?,如示例:

2.5 如何确定可为空的值类型

如果要确定实例是否是可为空的值类型,请不要使用Object.GetType方法获取要通过前面的代码测试的Type实例。如果对值类型可为空的实例调用Object.GetType方法,该实例将装箱到Object。由于对可为空的值类型的非NULL实例的装箱等同于对基础类型的值的装箱,因此GetType会返回表示可为空的值类型的基础类型的Type实例。

另外,请勿使用is运算符来确定实例是否是可为空的值类型。因为无法使用is运算符区分可为空值类型实例的类型与其基础类型实例。

综合来说,如果要判断可为空值类型,需要使用Nullable.GetUnderlyingTypetypeof运算符。以检查实例是否具有可为空的值类型。

三、可为 null 的引用类型

由于可为null的感知上下文选择加入代码,可以使用可为null的引用类型。可为null的引用类型,null静态分析警告和null包容运算符是可选的语言功能。

在可为null的感知上下文中:

  • 引用类型T的变量必须用非null值进行初始化,并且不能为其分配可能为null的值。
  • 引用类型T?的变量可以用null进行初始化,也可以分配null,但是在取消引用之前必须对null进行验证检测。
  • 类型为T?的变量m在应用null包含运算符时被认为是非空的。

不可为null的引用类型T和可为null的引用类型T?之间的区别按照编译器对上述规则的解释强制执行的,类型为T的变量和类型为T?的变量由相同的.NET类型表示。

string notNull = "Hello";
string? nullable = default;
notNull = nullable!;
Console.WriteLine(notNull);

变量notNull和nullable都由String类型表示。因为不可为null的类型和可为null的类型都存储为相同的类型,所以有几个位置不允许使用可为null的引用类型。

下面几种情况不能使用可为nulll类型

  • 可为 null 的引用类型不能用作基类或实现的接口
  • 可为 null 的引用类型不能用于任何对象创建或类型测试表达式
  • 可为 null 的引用类型不能是成员访问表达式的类型
public MyClass : System.Object? // not allowed
{
}var nullEmpty = System.String?.Empty; // Not allowed
var maybeObject = new object?(); // Not allowed
try
{if (thing is string? nullableString) // not allowedConsole.WriteLine(nullableString);
} catch (Exception? e) // Not Allowed
{Console.WriteLine("error");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/340760.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低压系统母线为什么必须装设弧光保护

安科瑞武陈燕acrelcy 1 重视中低压母线故障的原因 我国电力发展建设的速度超前&#xff0c;它已经进入人电网、大机组、压输电阶段&#xff0c;并且对发电机组的容量要求越来越高&#xff0c;这时就需要在安全运行方面要跟上要求&#xff0c;因为单台大机组的运行情况&#x…

UG装配-动态干涉检查

如果设计的产品有运动部件&#xff0c;除了做静态干涉检查外&#xff0c;通常还要做动态干涉检查 动态检查可以使用如下命令&#xff1a;移动组件&#xff0c;序列 在动态干涉检查前&#xff0c;先装配好组件&#xff0c;并且是可运动状态 在使用移动组件命令对运动部件进行…

java实现AES256对称加解密工具类

一、引入依赖包 引入相关依赖包 <dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version> </dependency> <!--lombok用于简化实体类开发--> <dependency&g…

RT-Thread入门笔记3-线程的创建

线程 RT-Thread 中&#xff0c;线程由三部分组成&#xff1a;线程代码&#xff08;入口函数&#xff09;、线程控制块、线程堆栈. 线程代码: 线程控制块 : 线程控制块是操作系统用于管理线程的一个数据结构&#xff0c; 它会存放线程的一些信息&#xff0c; 例如优先级、 线程…

Python知识点(史上最全)

Python期末考试知识点&#xff08;史上最全&#xff09; python简介 Python是一种解释型语言 Python使用缩进对齐组织代码执行&#xff0c;所以没有缩进的代码&#xff0c;都会在载入时自动执行 数据类型&#xff1a;整形 int 无限大 浮点型 float…

YOLOv8 + openVINO 多线程数据读写顺序处理

多线程数据读写顺序处理 一个典型的生产者-消费者模型&#xff0c;在这个模型中&#xff0c;多个工作线程并行处理从共享队列中获取的数据&#xff0c;并将处理结果以保持原始顺序的方式放入另一个队列。 多线程处理模型&#xff0c;具体细节如下&#xff1a; 1.数据:数据里必…

【MySQL】锁机制

文章目录 一、表级锁和行级锁二、排他锁和共享锁三、InnoDB行级锁行级锁间隙锁意向共享锁和意向排他锁 四、InnoDB表级锁五、死锁六、锁的优化建议 一、表级锁和行级锁 表级锁&#xff1a; 对整张表加锁。开销小&#xff0c;加锁快&#xff0c;不会出现死锁&#xff1b;锁粒度…

【JaveWeb教程】(19) MySQL数据库开发之 MySQL数据库操作-DML 详细代码示例讲解

目录 3. 数据库操作-DML3.1 增加(insert)3.2 修改(update)3.3 删除(delete)3.4 总结 3. 数据库操作-DML DML英文全称是Data Manipulation Language(数据操作语言)&#xff0c;用来对数据库中表的数据记录进行增、删、改操作。 添加数据&#xff08;INSERT&#xff09;修改数据…

ROS-urdf集成gazebo

文章目录 一、URDF与Gazebo基本集成流程二、URDF集成Gazebo相关设置三、URDF集成Gazebo实操四、Gazebo仿真环境搭建 一、URDF与Gazebo基本集成流程 1.创建功能包 创建新功能包&#xff0c;导入依赖包: urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_plugins 2.编写URD…

MacOS安装Miniforge、Tensorflow、Jupyter Lab等(2024年最新)

大家好&#xff0c;我是邵奈一&#xff0c;一个不务正业的程序猿、正儿八经的斜杠青年。 1、世人称我为&#xff1a;被代码耽误的诗人、没天赋的书法家、五音不全的歌手、专业跑龙套演员、不合格的运动员… 2、这几年&#xff0c;我整理了很多IT技术相关的教程给大家&#xff0…

【AI视野·今日Robot 机器人论文速览 第七十三期】Tue, 9 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Tue, 9 Jan 2024 Totally 40 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Digital Twin for Autonomous Surface Vessels for Safe Maritime Navigation Authors Daniel Menges, Andreas Von Brandis, A…

【AI视野·今日Sound 声学论文速览 第四十四期】Tue, 9 Jan 2024

AI视野今日CS.Sound 声学论文速览 Tue, 9 Jan 2024 Totally 27 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers DJCM: A Deep Joint Cascade Model for Singing Voice Separation and Vocal Pitch Estimation Authors Haojie Wei, Xueke Cao, Wenbo Xu…