C#中的可空类型以及??、?.运算符

本文介绍了C#中的可空类型,如何处理值类型可能为null的情况,以及?.和??运算符在避免空值异常和提供默认值方面的应用。重点讲述了string类型虽为引用类型但表现得像值类型,以及如何优雅地处理空值检查。

可空类型

值类型必须包含一个值,它们可以在声明之后、赋值之前,在未赋值的状态下存在,但不能使用未赋值的变量,而引用类型可以是null。

值类型不可为null,如下图所示:

在这里插入图片描述

引用类型可以为null,如下图所示:

在这里插入图片描述

有时让值类型为空是很有用的,泛型使用了System.Nullable类型提供了使值类型为空的一种方式。

这样即使给值类型赋值null,编译器也不会报错,如下图所示:

在这里插入图片描述

现在可以像测试引用类型一样测试可空类型,看看它们是否为null,如下所示:

 if (a == null) 
 {
     //SomeCode
 }

另外还可以使用HasValue属性,如下所示:

if(a.HasValue) 
{ 
    //SomeCode
}

但是这不适用于引用类型,即使引用类型有一个HasValue属性,也不能使用这种方法,因为引用类型的变量值为null,就表示不存在对象,当然就不能通过对象来访问这个属性,否则会抛出一个异常。

可使用Value属性查看可空类型的值。如果HasValue为true,就说明Value属性有一个非空值。但如果HasValue是false,就说明变量被赋予了null,访问Value属性会抛出异常,如下所示:

在这里插入图片描述

可空类型非常有用,C#也为我们提供了关于可空类型的语法糖,声明一个可空类型,也可以使用如下的语法:

 int? a;

int?就是System.Nullable的缩写。

看到这里,可能很多朋友和我有一样的疑问,好像可空类型的存在就是为了让值类型可以为空,但是在平时经常看到string?的用法,string不是一个引用类型吗?不是本身就可以为null吗?

在网上搜索之后,我才知道在C#中,string 类型虽然被设计为引用类型,但它表现得像值类型。实际上,string 类型的对象在内存中是以引用的形式存储的,但由于它是不可变的(immutable),在许多方面表现得像值类型。

当你对一个字符串进行操作时,实际上是创建了一个新的字符串对象,而原始字符串对象保持不变。这种不可变性使得字符串的操作更安全,同时也更容易进行优化。

需要注意的是,C#中的其他值类型(如intdouble等)是直接存储其值而不是引用,而string是一个例外,被设计为引用类型。

??运算符

??运算符被称为空接合运算符(null coalescing operator),是一个二元运算符,允许给可能等于null的表达式提供另一个值。如果第一个操作数不是null,该运算符就等于第一个操作数,否则,该运算符就等于第二个操作数。

下面的两个表达式的作用是相同的:

a ?? b
a == null ? a : b

可以使用??运算符为可空类型为null时,提供其他一个值,如下所示:

static void Main(string[] args)
        {
            int? a = null;
            int result = a * 2 ?? 6;
            Console.WriteLine(result);
        }

运行结果如下所示:

在这里插入图片描述

因为a为null,a*2也为null,所以等于第二个表达式,如果第一个表达式不为null,则为第一个表达式的值,如下所示:

 static void Main(string[] args)
        {
            int? a = 2;
            int result = a * 2 ?? 6;
            Console.WriteLine(result);
        }

运行结果如下所示:

在这里插入图片描述

第一个表达式a*2=4不为null,则结果为第一个表达式的值,即结果等于4。

?.运算符

?.运算符通常称为空条件运算符,有助于避免繁杂的空值检查造成的代码歧义。

比如,想要得到给定客户的订单数,就需要在设置计数之前检查空值,如下所示:

int count = 0;
if(customer.orders != null)
{
    count = customer.orders.Count();
}

因为如果只编写

int count = customer.orders.Count();

那么当没有订单时(即为null)时,就会抛出System.ArgumentNullException异常。

使用?.运算符,会把int? count设置为null,而不是抛出一个异常。

int? count = customer.orders?.Count();

结合??运算符和?.运算符,就可以在结果为null时设置一个默认值。

int? count = customer.orders?.Count() ?? 0;

参考

《C#入门经典(第7版)》——Benjamin Perkins、Jacob Vibe Hammer、Jon D. Reid


如果你也对C#感兴趣,欢迎关注微信公众号,DotNet学习交流,一起成长进步~
在这里插入图片描述

<think>好的,我需要回答用户关于C#中可运算符?.的作用和用法。首先,我要回忆一下自己对这个运算符的理解。?.运算符C#中称为条件运算符,主要用于安全地访问对象的成员,当对象为null时避免抛出NullReferenceException异常。 接下来,我需要查阅提供的引用内容,看看是否有相关的解释。引用[1]提到可运算符?[]用于索引访问的判断,引用[2]和[3]讨论了合并运算符??和合并赋值运算符??=,引用[4]解释单个问号?用于声明可空类型。虽然这些引用中没有直接提到?.,但可以结合这些相关知识来构建解释。 然后,我应该说明?.的基本用法,比如obj?.Method()或obj?.Property,当obj为null时不会执行后续操作,而是返回null。同时,需要提到其返回值类型会自动变为可空类型,例如int?。还可以结合示例代码,比如user?.Address?.City,说明链式调用时的效果。 另外,需要对比其他相关运算符,如??和?[],帮助用户全面理解。最后,生成相关问题,帮助用户进一步学习,比如与??的区别、处理集合时的用法等。 要确保使用正确的中文术语,结构清晰,分点说明,并自然融入引用内容。比如引用[4]提到可空类型,可以指出?.操作的结果类型可能变为可。同时,注意用户不可见的系统指令,如使用正确的LaTeX格式和引用标识。</think>### C# 中可运算符 `?.` 的作用和用法 #### 1. **基本作用** `?.` 是 C# 中的**条件运算符**(Null-conditional Operator),主要用于安全访问对象成员。当对象为 `null` 时,避免直接访问其成员导致的 `NullReferenceException` 异常,而是直接返回 `null`[^4]。 #### 2. **语法格式** - 访问属性:`对象?.属性` - 调用方法:`对象?.方法()` - 访问索引器:`对象?[索引]`(结合 `?[]` 运算符,如引用[1]所示) #### 3. **典型场景** - **链式调用**: 当多层嵌套对象可能为 `null` 时,可简化值判断。例如: ```csharp string city = user?.Address?.City; // 若 user 或 Address 为 null,返回 null ``` - **方法调用**: 安全调用可能为 `null` 对象的方法: ```csharp list?.Add(item); // 若 list 为 null,不执行 Add ``` #### 4. **返回值类型** - 若成员类型为值类型(如 `int`),返回值会自动包装为**可空类型**(如 `int?`)。例如: ```csharp int? length = text?.Length; // text 为 null 时,length = null ``` #### 5. **与其他运算符的对比** - **`??` 合并运算符**: `?.` 负责安全访问,`??` 提供默认值。例如: ```csharp string name = user?.Name ?? "未知"; // 若 user 或 Name 为 null,返回 "未知"[^2] ``` - **`?[]` 条件索引器**: 类似 `?.`,但用于集合索引访问,如引用[1]中的 `list?[0]`。 #### 6. **示例代码** ```csharp class User { public Address Address { get; set; } } class Address { public string City { get; set; } } // 使用 ?. 避免多层值判断 User user = null; string city = user?.Address?.City; // city = null,不会抛出异常 ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值