时间:2021-05-20
顶级语句可以删除程序中不必要的代码, 以最简单的 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) => { };创建只能通过对象初始化进行赋值的属性。
public class InitDemo { public string Start { get; init; } public string Stop { get; init; }}// initDemo.Start = "Now"; // Error// initDemo.End = "Tomorrow"; // Errorvar initDemo = new InitDemo { Start = "Now", Stop = "Tomorrow"};记录类型, 是一种引用类型, 默认是不可变的。 记录类型的相等判断可以通过引用或者结构进行判断的。
// 默认不可变的记录类型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 包含了一些新的模式匹配增强:
注意, 如果没有匹配到全部的情况, 将会出现异常。
在C#9.0中,当已创建对象的类型已知时,可以在new表达式中省略该类型。
public class MyClass { private List<WeatherObservation> _observations = new();}Point p = new(1, 1);Dictionary<string, int> dict = new();Point[] points = { new(1, 1), new (2, 2), new (3, 3) };var list = new List<Point> { new(1, 1), new(2, 2), new(3, 3)};可以隐式转换 null 值, 在 C#9.0 中得到了增强。
void TestMethod(int[] list, uint? u) { int[] x = list ?? new int[0]; var l = u ?? -1u;}可以为任意类型添加一个 GetEnumerator<T> 扩展, 返回一个 IEnumerator<T> 或者 IAsyncEnumerator<T> 实例, 从而在 foreach 循环中使用。
public static class Extensions { public static IEnumerator<T> GetEnumerator<T>(this IEnumerator<T> enumerator) => enumerator;}IEnumerator<string> enumerator = new Collection<string> { "A", "B", "C"}.GetEnumerator();foreach (var item in enumerator) { Console.WriteLine(item);}允许在本地函数上添加标记。
static void Main(string[] args) { [Conditional("DEBUG")] static void DoSomething([NotNull] string test) { Console.WriteLine("Do it!"); } DoSomething("Doing!");}在C#9.0中,移除了分部方法的几个限制:
从 C#9.0 开始,可以将 static 修饰符添加到 lambda 表达式或 匿名方法 。静态 lambda 表达式类似于 static 局部函数:静态lambda或匿名方法无法捕获局部变量或实例状态。 所述 static 可以防止意外捕获其他变量。
lambda 表达式会捕获上下文的变量,不仅会有性能的问题,而且还可能出现错误,比如:
int number = 0;Func<string> toString = () => number.ToString(); // number 被自动捕获进 toString 函数中可以在 lambda 表达式前添加 static 关键字, 来解决这个问题:
int number = 0;Func<string> toString = static () => number.ToString(); // 这里无法再使用 number ;可以使用 ModuleInitializerAttribute 为组件 (assembly) 定义初始化代码, 当初始化/加载时执行, 可以类比类的静态构造函数, 但是是组件级别的, 要求如下:
协变返回类型为重写方法的返回类型提供了灵活性。覆盖方法可以返回从覆盖的基础方法的返回类型派生的类型。这对于记录和其他支持虚拟克隆或工厂方法的类型很有用。 比如:
public virtual Person GetPerson() { return new Person(); }public override Person GetPerson() { return new Student(); }在 C# 9.0 中, 可以在子类中返回更加详细的类型:
public virtual Person GetPerson() { return new Person(); }public Student Person GetPerson() { return new Student(); }C#9 添加了两个新的整数类型 (nint 和 nunit) , 依赖宿主机以及编译设定。
nint nativeInt = 55;Console.WriteLine(nint.MaxValue);// 在 x86 平台上, 输出为 2147483647// 在 x64 平台上, 输出为 9223372036854775807在 C#9.0 中,可以使用 SkipLocalsInitAttribute 来告知编译器不要发射 (Emit) .locals init 标记。
[System.Runtime.CompilerServices.SkipLocalsInit]static unsafe void DemoLocalsInit() { int x; // 注意, x 没有初始化, 输出结果不确定; Console.WriteLine(*&x);}使用 delegate* 可以声明函数指针。
unsafe class FunctionPointer { static int GetLength(string s) => s.Length; delegate*<string, int> functionPointer = &GetLength;}public void Test() { Console.WriteLine(functionPointer("test")); // 4;}以上就是C# 9.0 特性全面总结的详细内容,更多关于C# 9.0 特性的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例总结了C#XML序列化方法及常用特性。分享给大家供大家参考,具体如下:C#对象XML序列化(一):序列化方法和常用特性.NetFramework提供了对
在之前的文章中介绍了C#是一种完全面向对象的语言,既然是完全面向对象的语言就应该用面向对象的模式去学习C#,不了解面向对象?不必担心。这篇文章将介绍学习C#基础
前言翻译自MadsTorgersen2020年5月20日的博文《WelcometoC#9.0》,MadsTorgersen是微软C#语言的首席设计师,也是微软.
记得在MSBuild2020大会上,C#语言开发项目经理MadsTorgersen宣称C#9.0将会随着.NET5在今年11月份正式发布。目前.NET5已经到了
由C#转入Java一段时间了,总结下个人认为的Java同C#语法之间的不同之处,有不同意见之处还望各位海涵刚学Java时觉得语法同C#大致是相同的(应该说C#同