网站首页 > 技术文章 正文
可空类型(Nullable)是一个极具实用性的特性,它为我们处理那些可能出现未赋值情况的数据提供了便捷且合理的方式。而其中,单问号(?)和双问号(??)这两个符号在可空类型的运用中扮演着关键角色,各自有着独特且重要的功能
一、单问号(?)
在 C# 中,像 int、double、bool 等这些基础的数据类型,按照常规情况是无法直接赋值为 null 的。然而,实际编程场景中,尤其是在处理诸如数据库等外部数据源时,常常会遇到数值类型或者布尔型的元素可能未被赋值的情况。这时,单问号(?)就派上用场了,它用于将这些原本不能赋值为 null 的数据类型转变为可空类型(Nullable 类型),意味着这个数据类型被赋予了可以存储 null 值的能力。
例如,以下两种写法是等价的:
int? i = 3;
Nullable<int> i = new Nullable<int>(3);
通过使用单问号(?),我们定义了一个可空的整型变量 i,它既可以像普通整型变量那样存储 int 类型正常范围内的值(例如 3),也可以存储 null 值。对比普通的整型变量声明:
int i; // 默认值 0
int? ii; // 默认值 null
可以清晰地看到,普通整型变量在未初始化赋值时,会有一个默认的初始值 0,而可空整型变量 ii 的默认值则是 null,这体现了可空类型在表示未赋值情况方面的独特优势。
以 Nullable 为例,它读作 “可空的 Int32”,其取值范围非常灵活,不仅可以被赋值为 -2,147,483,648 到 2,147,483,647 之间的任意值(这是 Int32 类型本身正常的取值范围),还可以被赋值为 null 值。类似地,对于 Nullable 变量而言,它打破了常规布尔型只能取 true 或 false 的限制,额外增加了可以赋值为 null 的能力,这在很多场景下都非常有用。
比如在处理数据库相关操作时,数据库中的布尔型字段可能会出现三种状态:存储值 true、存储值 false,或者该字段未定义(也就是对应程序中的 null 值)。可空类型就能完美地适配这种情况,让我们在程序中可以准确地映射和处理数据库中的数据状态,避免因数据可能未赋值而引发的错误或不合理的默认赋值情况。
声明一个可空类型(Nullable)有着特定的语法规范,其形式如下:
<data_type>? <variable_name> = null;
以下是一个展示可空数据类型用法的实例:
using System;
namespace CalculatorApplication
{
class NullablesAtShow
{
static void Main(string[] args)
{
// 声明不同的可空类型变量,并进行不同的赋值操作
int? num1 = null;
int? num2 = 45;
double? num3 = new double?();
double? num4 = 3.14157;
bool? boolval = new bool?();
// 显示值
Console.WriteLine("显示可空类型的值: {0}, {1}, {2}, {3}",
num1, num2, num3, num4);
Console.WriteLine("一个可空的布尔值: {0}", boolval);
Console.ReadLine();
}
}
}
当上述代码被编译和执行时,会输出如下结果:
显示可空类型的值:, 45, , 3.14157
一个可空的布尔值:
这里可以看到,对于赋值为 null 的可空变量(如 num1 和 num3),在输出时会显示相应的空白占位(具体输出格式可能因不同环境稍有差异,但能体现出其值为 null 的特点),而赋了具体值的可空变量(如 num2 和 num4)则正常输出对应的值,可空布尔型变量 boolval 由于初始化为 null,输出时也相应地体现出未赋值的状态。
二、双问号(??)
双问号(??)被称为 Null 合并运算符,它主要用于定义可空类型和引用类型的默认值,为类型转换设定了一个预设值,以防可空类型的值为 null。
Null 合并运算符的特性:如果第一个操作数的值为 null,那么运算符就返回第二个操作数的值;反之,如果第一个操作数不为 null,则返回第一个操作数的值。它还能够把操作数类型隐式转换为另一个可空(或不可空)的值类型的操作数的类型,确保整个运算在类型匹配方面的合理性。
以下是一个演示 Null 合并运算符用法的实例:
using System;
namespace CalculatorApplication
{
class NullablesAtShow
{
static void Main(string[] args)
{
double? num1 = null;
double? num2 = 3.14157;
double num3;
// 使用 Null 合并运算符进行赋值判断
num3 = num1?? 5.34; // 因为 num1 此时为 null 值,所以返回 5.34
Console.WriteLine("num3 的值: {0}", num3);
num3 = num2?? 5.34;
Console.WriteLine("num3 的值: {0}", num3);
Console.ReadLine();
}
}
}
当这段代码被编译和执行后,会产生如下结果:
num3 的值: 5.34
num3 的值: 3.14157
在上述代码中,第一次对 num3 赋值时,由于 num1 的值为 null,根据 Null 合并运算符(??)的规则,就会返回第二个操作数 5.34 作为 num3 的值;而第二次赋值时,num2 的值不为 null(其值为 3.14157),所以直接返回 num2 的值给 num3。
这种机制在实际编程中有诸多应用场景,比如在从配置文件或者用户输入获取数据时,数据有可能是缺失(对应 null 值)的情况。我们可以利用 Null 合并运算符为这些可能为 null 的可空类型变量设置一个合理的默认值,确保后续程序在使用这些数据时能够有一个明确的、符合预期的值可用,避免因 null 值引发的诸如空指针异常等各种错误。
- 上一篇: C# (一)状态机模式(状态机代码实现)
- 下一篇: C#中使用Halcon开发视觉检测程序教程
猜你喜欢
- 2025-07-24 Channels: C# 实现高效的线程间通信
- 2025-07-24 一路踩坑,被迫聊聊 C# 代码调试技巧和远程调试
- 2025-07-24 C# 获取Windows的系统信息(c# 获取本机的ip地址)
- 2025-07-24 C# 读取本地网络配置信息(c# 读取配置文件的方法)
- 2025-07-24 MODBUS协议在C#中的应用案例(c#modbus 程序)
- 2025-07-24 C#接口(c接口镜头)
- 2025-07-24 AngleSharp :在 C# 中轻松解析和操作 HTML/XML 文档
- 2025-07-24 C#中的9个“黑魔法”与“骚操作”
- 2025-07-24 C#.NET Ninject 详解(c#.net framework)
- 2025-07-24 C#.NET HttpClient 使用教程(c#开启http服务)
- 1517℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 594℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 521℃MySQL service启动脚本浅析(r12笔记第59天)
- 489℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 489℃启用MySQL查询缓存(mysql8.0查询缓存)
- 477℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 456℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 454℃MySQL server PID file could not be found!失败
- 最近发表
-
- PS所有滤镜的说明(六)(ps滤镜详解)
- 5款小白也能用的在线图片编辑器!电商效率飙升就靠它!
- Java变量(java变量有什么作用)
- Java面试常见问题:Java注解(java中的面试题)
- Java编程入门第一课:HelloWorld(java编程从入门到实践)
- Java基础教程:Java继承概述(java里继承的概述)
- java基础之——访问修饰符(private/default/protected/public)
- 如何规划一个合理的JAVA项目工程结构
- 将机器指令翻译成 JavaScript -- 终极目标
- Web 服务器基准测试:Go vs. Node.js vs. Nim vs. Bun
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)