-
c#中关于Nullable类型与空合并——用户信息补全工具
Nullable类型与空合并——用户信息补全工具
实例介绍
在开发中,缺失信息是常见场景:用户可能没填年龄、数据库字段允许空值、接口返回可选参数。Nullable类型(可空类型)解决了“值类型不能为null”的痛点,空合并运算符(??)则简化了空值的默认赋值逻辑。本实例通过实现用户信息补全工具,掌握Nullable类型的声明与使用、空合并运算符的简洁语法,以及如何优雅处理缺失信息,让程序在面对空值时更健壮、代码更简洁。
需求分析
1.存储可选信息:用户年龄、手机号、邮箱为可选字段,允许为空;
2.补全缺失信息:对空值字段设置默认值(如年龄为空设18、手机号为空设“未知”);
3.处理用户输入:用户未输入可选字段时,保留null而非强制赋值;
4.避免空引用异常:用空条件运算符(?.)安全处理输入的空值;
5.友好展示:补全前后的用户信息对比,清晰呈现空值处理效果。
代码实现
csharp
using System;
namespace NullableAndNullCoalescingDemo
{
// 用户信息类:包含可选字段(Nullable类型)
public class UserInfo
{
// 必填字段:非空字符串(C#8+ 启用Nullable引用类型时,未标记?的引用类型默认非空)
public string Name { get; set; }
// 可选字段:Nullable值类型(年龄可空)
public int? Age { get; set; }
// 可选字段:Nullable引用类型(手机号、邮箱可空)
public string? Phone { get; set; }
public string? Email { get; set; }
// 重写ToString:友好展示用户信息
public override string ToString()
{
return $"姓名:{Name}
年龄:{Age}
手机号:{Phone}
邮箱:{Email}";
}
}
class UserInfoCompletor
{
static void Main(string[] args)
{
Console.WriteLine("=== 用户信息输入 ===");
UserInfo user = InputUserInfo();
Console.WriteLine("
=== 补全前的用户信息 ===");
Console.WriteLine(user.ToString());
Console.WriteLine("
=== 补全后的用户信息 ===");
UserInfo completedUser = CompleteUserInfo(user);
Console.WriteLine(completedUser.ToString());
Console.ReadKey();
}
// 输入用户信息:处理空值输入
public static UserInfo InputUserInfo()
{
// 姓名必填:用空条件运算符?.避免空引用,若输入null则抛出异常
Console.Write("请输入姓名(必填):");
string name = Console.ReadLine()?.Trim() ?? throw new ArgumentNullException("姓名不能为空!");
// 年龄可选:用户未输入则设为null
Console.Write("请输入年龄(可选,直接回车表示未填写):");
string ageInput = Console.ReadLine()?.Trim() ?? "";
int? age = string.IsNullOrEmpty(ageInput) ? null : (int.TryParse(ageInput, out int a) ? a : null);
// 手机号可选:直接接收空值
Console.Write("请输入手机号(可选):");
string? phone = Console.ReadLine()?.Trim();
// 邮箱可选:直接接收空值
Console.Write("请输入邮箱(可选):");
string? email = Console.ReadLine()?.Trim();
return new UserInfo { Name = name, Age = age, Phone = phone, Email = email };
}
// 补全用户信息:用空合并运算符设置默认值
public static UserInfo CompleteUserInfo(UserInfo user)
{
// 空合并赋值运算符 ??=:左边为null时赋值右边
user.Age ??= 18; // 年龄空→默认18
user.Phone ??= "未知手机号"; // 手机号空→默认"未知手机号"
user.Email ??= "未填写邮箱"; // 邮箱空→默认"未填写邮箱"
return user;
}
}
}
逐行讲解
-
UserInfo类:Nullable类型的声明
csharp
public int? Age { get; set; } // 等价于 NullableAge
public string? Phone { get; set; } // C#8+ Nullable引用类型
int?:值类型的可空形式,允许存储null(普通int无法存储null);
string?:引用类型的显式可空标记(C#8+特性),编译器会提示“该字段可能为null”,减少空引用异常;
为什么用Nullable:比如用户未填年龄时,不能用int age=0(0是有效年龄,会误导),用int? age=null更准确。 -
InputUserInfo:处理用户输入的空值
csharp
string name = Console.ReadLine()?.Trim() ?? throw new ArgumentNullException(...);
Console.ReadLine()?.Trim():空条件运算符?.,若输入为null(用户直接回车),则不调用Trim(),避免空引用异常;
??:空合并运算符,左边为null时执行右边逻辑(这里抛出异常,因为姓名必填);
csharp
int? age = string.IsNullOrEmpty(ageInput) ? null : (int.TryParse(ageInput, out int a) ? a : null);
用户未输入年龄(ageInput为空)→设为null;
输入无效(如“abc”)→也设为null,保留原始缺失状态。 -
CompleteUserInfo:空合并赋值的简化
csharp
user.Age ??=18; // 等价于 if(user.Age == null) user.Age=18;
??=:C#8+新增的空合并赋值运算符,左边为null时才赋值,代码更简洁;
对比传统写法:user.Phone = user.Phone ?? "未知手机号";,??=省去了重复的user.Phone。
基础知识拓展 -
Nullable类型的本质
Nullable类型是结构体(Nullable),包含两个核心属性:
HasValue:bool类型,标记是否有有效值;
Value:T类型,存储实际值(若HasValue=false,访问Value会抛出InvalidOperationException)。
示例:
csharp
int? age = null;
Console.WriteLine(age.HasValue); // false
// Console.WriteLine(age.Value); // 抛出异常
age =18;
Console.WriteLine(age.HasValue); // true
Console.WriteLine(age.Value); //18
-
空合并运算符 vs 三元运算符
空合并运算符(??)是三元运算符的简化版,专门处理空值:
csharp
// 三元运算符:繁琐
string phone = user.Phone != null ? user.Phone : "未知手机号";
// 空合并运算符:简洁
string phone = user.Phone ?? "未知手机号";
-
Nullable引用类型的启用
要使用string?等Nullable引用类型,需在项目文件中添加:
xml
<PropertyGroup>
<Nullable>enable</Nullable> <!-- 或 strict:强制检查所有空引用 -->
</PropertyGroup>
或在代码顶部加#nullable enable,编译器会自动提示可能的空引用风险。
4. 空条件运算符的连锁使用
?.可连锁调用,避免多层空判断:
csharp
// 传统写法:多层if
if(user != null && user.Address != null) Console.WriteLine(user.Address.City);
// 空条件运算符:简洁
Console.WriteLine(user?.Address?.City); // 任何一层为null则返回null
扩展思考
1.数据库映射:结合EF Core,数据库中允许空的字段(如Age)对应实体类的int? Age,避免类型不匹配;
2.空合并链:用a??b??c设置多级默认值,比如user.Email ?? user.Phone ?? "无联系方式";
3.自定义默认值:让用户指定默认值(如int defaultAge=20),而非固定18;
4.严格空检查:启用Nullable=strict,强制处理所有可能的空引用,彻底消灭空异常;
5.Optional模式:用Optional
总结
Nullable类型解决了“值类型不能为null”的痛点,空合并运算符简化了空值的默认赋值逻辑,两者结合是处理缺失信息的最佳实践。无论是用户输入、数据库查询还是接口返回,这些技巧都能让代码更简洁、健壮,避免空引用异常和误导性的默认值。掌握它们,你就能优雅应对开发中的各种空值场景。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49399.html










