404 Not Found

404 Not Found


nginx

可空类型与模式匹配

可空值类型

值类型默认不能为 nullNullable<T> 结构体(简写为 T?)让值类型可以承载空值语义。

CSHARP
int? a = 42;
int? b = null;
bool? flag = null;
double? price = 9.99;

Console.WriteLine(a.HasValue);
Console.WriteLine(b.HasValue);
Console.WriteLine(flag.GetValueOrDefault());
Console.WriteLine(price.GetValueOrDefault(0.0));
TEXT
True
False
False
9.99

示例

CSHARP
int? score = null;

Console.WriteLine(score.HasValue);
Console.WriteLine(score.GetValueOrDefault());
Console.WriteLine(score.GetValueOrDefault(60));

score = 88;
Console.WriteLine(score.Value);
▶ 试一试
TEXT
False
0
60
88

空合并与空条件运算符

?? 提供默认值,?. 安全访问成员,! 告诉编译器"此处不为 null"。

CSHARP
int? x = null;
int y = x ?? 0;

string? name = null;
int? len = name?.Length;

string s = null!;
Console.WriteLine(s is null);
TEXT
True

示例

CSHARP
string? input = null;

string display = input ?? "(空)";
Console.WriteLine(display);

int? length = input?.Length;
Console.WriteLine(length ?? -1);

string? city = "北京";
Console.WriteLine(city?.Length ?? 0);
▶ 试一试
TEXT
(空)
-1
2

可空引用类型

C# 8 起可用 #nullable enable 开启可空引用类型警告。string? 允许为 null,string 不允许。

CSHARP
#nullable enable
string? maybeNull = null;
string notNull = "hello";

maybeNull = null;
notNull = null!;

示例

CSHARP
#nullable enable
string Greet(string? name)
{
    return name is null ? "你好,陌生人" : $"你好,{name}";
}

Console.WriteLine(Greet(null));
Console.WriteLine(Greet("小明"));
▶ 试一试
TEXT
你好,陌生人
你好,小明

null 检查策略

策略 用法 场景
显式判断 if (x is null) 需要分支逻辑
空合并 x ?? defaultValue 提供默认值
空条件 x?.Member 安全访问成员

示例

CSHARP
string? GetName() => null;

string? name = GetName();

if (name is null)
{
    Console.WriteLine("名字为空");
}

string upper = name?.ToUpper() ?? "DEFAULT";
Console.WriteLine(upper);
▶ 试一试
TEXT
名字为空
DEFAULT

模式匹配初识

模式匹配让类型检查与变量提取合二为一,常用在 isswitch 中。

is 模式

CSHARP
object obj = 42;

if (obj is int i)
{
    Console.WriteLine($"是整数:{i}");
}
TEXT
是整数:42

示例

CSHARP
object value = "hello";

if (value is int n)
{
    Console.WriteLine(n);
}
else if (value is string s)
{
    Console.WriteLine($"字符串长度:{s.Length}");
}
▶ 试一试
TEXT
字符串长度:5

类型模式与 switch

switch 中按类型分支并提取变量。

示例

CSHARP
string Describe(object obj)
{
    return obj switch
    {
        int i => $"整数 {i}",
        double d => $"双精度 {d}",
        string s => $"字符串 \"{s}\"",
        bool b => $"布尔 {b}",
        null => "null",
        _ => "未知类型"
    };
}

Console.WriteLine(Describe(10));
Console.WriteLine(Describe(3.14));
Console.WriteLine(Describe("hi"));
Console.WriteLine(Describe(true));
▶ 试一试
TEXT
整数 10
双精度 3.14
字符串 "hi"
布尔 True

属性模式

属性模式按对象属性匹配,无需手动取值比较。

示例

CSHARP
var person = new { Name = "小明", Age = 20 };

if (person is { Age: > 18 })
{
    Console.WriteLine("成年人");
}

string Category(object p) => p switch
{
    { Age: < 12 } => "儿童",
    { Age: >= 12 and < 18 } => "青少年",
    { Age: >= 18 } => "成年人",
    _ => "未知"
};

Console.WriteLine(Category(person));
▶ 试一试
TEXT
成年人
成年人

记录类型 record

C# 9 引入 record,自带值语义相等比较和不可变性。

CSHARP
record Person(string Name, int Age);

示例

CSHARP
record Person(string Name, int Age);

var p1 = new Person("小红", 18);
var p2 = new Person("小红", 18);

Console.WriteLine(p1 == p2);
Console.WriteLine(ReferenceEquals(p1, p2));
Console.WriteLine(p1);
▶ 试一试
TEXT
True
False
Person { Name = 小红, Age = 18 }

with 表达式

with 基于现有记录创建副本并修改部分属性,原实例不变。

示例

CSHARP
record Student(string Name, int Age, string Grade);

var s1 = new Student("小华", 20, "A");
var s2 = s1 with { Age = 21, Grade = "A+" };

Console.WriteLine(s1);
Console.WriteLine(s2);
▶ 试一试
TEXT
Student { Name = 小华, Age = 20, Grade = A }
Student { Name = 小华, Age = 21, Grade = A+ }

元组 Tuple

元组将多个值组合为一个轻量结构,支持命名元素与解构。

示例

CSHARP
(int Id, string Name) person = (1, "小刚");
Console.WriteLine(person.Id);
Console.WriteLine(person.Name);

var coords = (X: 3.0, Y: 4.0);
double distance = Math.Sqrt(coords.X * coords.X + coords.Y * coords.Y);
Console.WriteLine(distance);

(int x, int y) = (10, 20);
Console.WriteLine($"x={x}, y={y}");
▶ 试一试
TEXT
1
小刚
5
x=10, y=20

元组解构与模式匹配

元组与模式匹配结合可优雅处理多条件分支。

示例

CSHARP
string Classify(int score, bool hasBonus) => (score, hasBonus) switch
{
    (>= 90, true) => "卓越+奖励",
    (>= 90, false) => "卓越",
    (>= 60, true) => "及格+奖励",
    (>= 60, false) => "及格",
    _ => "不及格"
};

Console.WriteLine(Classify(95, true));
Console.WriteLine(Classify(75, false));
Console.WriteLine(Classify(50, true));
▶ 试一试
TEXT
卓越+奖励
及格
不及格

❓ 常见问题

Q int?int 可以直接运算吗?
A 不能,需要用 .Value?? 转为非空值再运算。
Q string?string 有什么区别?
A string? 允许赋值 null,string 在开启 nullable 后编译器会警告赋 null。
Q record 和 class 的核心区别?
A record 基于值判等(==比较内容),class 基于引用判等(==比较地址)。
Q with 表达式能否用于 class?
A 不能,with 仅适用于 record 或 init-only 属性的结构体。
Q 元组的元素数量有上限吗?
A ValueTuple 最多 8 个类型参数,超过时用嵌套 TRest 扩展。

📖 小节

📝 作业

  1. 声明 double? price = null;,用 GetValueOrDefault(99.9) 获取默认值并输出
  2. 编写方法接收 string? 参数,用 ?.?? 返回字符串长度或 -1
  3. is 模式判断 object obj = 3.14; 是否为 double d,输出 d * 2
  4. 定义 record Book(string Title, double Price);,创建实例并用 with 修改价格
  5. 用元组 switch 表达式实现 (int month, int day) 判断是否为"元旦"或"国庆"
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏