顶级语句
顶级语句可以删除程序中不必要的代码, 以最简单的 Hello, world! 为例:
using System; namespace HelloWorld { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } }
如果使用顶级语句的话, 可以简化为:
using System; Console.WriteLine("Hello World!");
如果不使用 using , 还可以更加简化:
System.Console.WriteLine("Hello World!");
顶级语句在很多命令行程序、小工具程序中会非常有用, 对应用程序的作用域或者复杂程度没有任何限制。
注意, 一个程序中, 只能有一个文件使用顶级语句, 并且顶级语句必须位于命名空间或类型定义之前!
弃元参数
在 lambda 表达式或者匿名函数中如果要忽略某个参数, 可以用 _ 代替。
var button = new Button("Click Me!"); button.Click += (_, e) => { /* other code goes here. */ };
仅初始化设置器 (Init only setters)
创建只能通过对象初始化进行赋值的属性。
public class InitDemo { public string Start { get; init; } public string Stop { get; init; } } // initDemo.Start = "Now"; // Error // initDemo.End = "Tomorrow"; // Error var initDemo = new InitDemo { Start = "Now", Stop = "Tomorrow" };
记录类型 (Record)
记录类型, 是一种引用类型, 默认是不可变的。 记录类型的相等判断可以通过引用或者结构进行判断的。
// 默认不可变的记录类型 public record Person(string Name, int Age); // 可变记录类型 public record MutablePerson(string Name, int Age) { public string Name { get; set; } = Name; public int Age { get; set; } = Age; } var person1 = new Person("Zhimin Zhang", 40); var person2 = new Person("Zhimin Zhang", 40); Console.WriteLine(person1 == person2); // True 结构相同 Console.WriteLine(person1.Equals(person2)); // True 结构相同 Console.WriteLine(ReferenceEquals(person1, person2)); // False, 引用不同 // 改变默认的记录! --> 创建一个新的记录。 var person3 = person1 with { Age = 43 }; Console.WriteLine(person3 == person1); // False 结构不同 // 解构 (Destruct) 一个记录, 将记录的属性提取为本地变量 var (name, age) = person3; var person4 = new MutablePerson("Zhimin zhang", 40); person4.Age = 43; var person5 = new Citizen("Zhimin Zhang", 40, "China"); Console.WriteLine(person1 == person5); // 记录类型也可以被继承 public record Citizen(string Name, int Age, string Country) : Person(Name, Age); var citizen = new Citizen("Zhimin Zhang", 40, "China"); Console.WriteLine(person1 == citizen); // False 类型不同;
- 优点:记录类型是轻量级的不可变类型,可以减少大量的代码, 可以按照结构和引用进行比较;
- 缺点:需要实例化大量的对象;
如果要更加深入的学习记录类型, 请查看微软的官方文档 exploration of records 。
模式匹配增强
C# 9 包含了一些新的模式匹配增强:
Type patterns 类型匹配,判断一个变量的类型
object obj = new int(); var type = obj switch { string => "string", int => "int", _ => "obj" }; Console.WriteLine(type); // int
Relational patterns 关系匹配
// Relational patterns var person1 = new Person("Zhimin Zhang", 40); var inRange = person1 switch { (_, < 18) => "less than 18", (_, > 18) => "greater t<i style="color:transparent">本文来源gaodai$ma#com搞$代*码6网</i>han 18", (_, 18) => "18 years old!" }; Console.WriteLine(inRange); // greater than 18
Conjunctive and patterns 逻辑与匹配
// And pattern var person1 = new Person("Zhimin Zhang", 40); var ageInRange = person1 switch { (_, < 18) => "less than 18", ("Zhang Zhimin", _) and (_, >= 18) => "Zhimin Zhang is greater than 18" }; Console.WriteLine(ageInRange); // Zhimin Zhang is greater than 18
Disjunctive or patterns 逻辑或匹配
// Or pattern var person1 = new Person("Zhimin Zhang", 40); var ageInRange = person1 switch { (_, < 18) => "less than 18", (_, 18) or (_, > 18) => "18 or greater" }; Console.WriteLine(ageInRange); // 18 or greater
Negated not patterns 逻辑非匹配
// Not pattern var person1 = new Person("Zhimin Zhang", 40); var meOrNot = person1 switch { not ("Zhimin Zhang", 40) => "Not me!", _ => "Me :-)" }; Console.WriteLine(meOrNot); // Me
Parenthesized patterns 带括号的优先级匹配
// Parenthesized patterns var is10 = new IsNumber(true, 10); var n10 = is10 switch { ((_, > 1 and < 5) and (_, > 5 and < 9)) or (_, 10) => "10", _ => "not 10" }; Console.WriteLine(n10); // 10