1.C# 8.0
C# 8.0在 dotNET Core 3.1 及以上版本中就可以使用 C# 8 的语法,下面是 C# 8 中我认为比较常用的一些新功能默认接口方法接口是用来约束行为的,在 C# 8 以前,接口中只能进行方法的定义,下面的代码在 C# 8 以前是会报编译错误的:。
2.c#9.0新特性
publicinterfaceIUser { stringGetName() => “oec2003”; }
3.C# 9.0
那么在 C# 8 中,可以正常使用上面的代码,也就是说可以对接口中的方法提供默认实现接口默认方法最大的好处是,当在接口中进行方法扩展时,之前的实现类可以不受影响,而在 C# 8 之前,接口中如果要添加方法,所有的实现类需要进行新增接口方法的实现,否则编译失败。
4.C# 8.0核心技术指南 pdf
C# 中不支持多重继承,主要的原因是会导致菱形问题:
5.C# 8.0和.NET Core 3.0高级编程
类 A 是一个抽象类,定义有一个 方法 Test;类 B 和 类 C 继承自抽象类 A,并有各自的实现;类 D 同时继承类 B 和类 C;当调用类 D 的 Test 方法时,就不知道应该使用 B 的 Test 还是 C 的 Test,这个就是菱形问题。
6.c#8.0核心技术指南
而接口是允许多继承的,那么当接口支持默认方法时,是否也会导致菱形问题呢?看下面代码:publicinterfaceIA { voidTest() => Console.WriteLine(“Invoke IA.Test”
); } publicinterfaceIB:IA { voidTest() => Console.WriteLine(“Invoke IB.Test”); } publicinterfaceIC
:IA { voidTest() => Console.WriteLine(“Invoke IC.Test”); } publicclassD : IB, IC { } staticvoid
Main(string[] args) { D d = new D(); d.Test(); } 上面的代码是无法通过编译的,因为接口的默认方法不能被继承,所以类 D 中没有 Test 方法可以调用,如下图:
所以,必须通过接口类型来进行相关方法的调用:staticvoidMain(string[] args){ IA d1 = new D(); IB d2 = new D(); IC d3 =
new D(); d1.Test(); // Invoke IA.Test d2.Test(); // Invoke IB.Test d3.Test(); // Invoke IC.Test
} 也正是因为必须通过接口类型来进行调用,所以也就不存在菱形问题而当具体的类中有对接口方法实现的时候,就会调用类上实现的方法:publicinterfaceIA { voidTest() => Console.WriteLine(。
“Invoke IA.Test”); } publicinterfaceIB:IA { voidTest() => Console.WriteLine(“Invoke IB.Test”); }
publicinterfaceIC:IA { voidTest() => Console.WriteLine(“Invoke IC.Test”); } publicclassD : IB, IC
{ publicvoidTest() => Console.WriteLine(“Invoke D.Test”); } staticvoidMain(string[] args) { IA d1 =
new D(); IB d2 = new D(); IC d3 = new D(); d1.Test(); // Invoke D.Test d2.Test(); // Invoke D.Test
d3.Test(); // Invoke D.Test } 类可能同时继承类和接口,这时会优先调用类中的方法:publicclassA { publicvoidTest() => Console.WriteLine(
“Invoke A.Test”); } publicinterfaceIA { voidTest() => Console.WriteLine(“Invoke IA.Test”); } public
classD : A, IA { } staticvoidMain(string[] args) { D d = new D(); IA d1 = new D(); d.Test();
// Invoke A.Test d1.Test(); // Invoke A.Test } 关于默认接口方法,总结如下:默认接口方法可以让我们在往底层接口中扩展方法的时候变得比较平滑;默认方法,会优先调用类中的实现,如果类中没有实现,才会去调用接口中的默认方法;
默认方法不能够被继承,当类中没有自己实现的时候是不能从类上直接调用的using 变量声明我们都知道 using 关键字可以导入命名空间,也能定义别名,还能定义一个范围,在范围结束时销毁对象,在 C# 8.0 中的 using 变量声明可以让代码看起来更优雅。
在没有 using 变量声明的时候,我们是这样使用的:staticvoidMain(string[] args) { var connString = “Host=221.234.36.41;Username=gpadmin;Password=123456;Database=postgres;Port=54320”
; using (var conn = new NpgsqlConnection(connString)) { conn.Open(); using (
var cmd = new NpgsqlCommand(“select * from user_test”, conn)) { using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) Console.WriteLine(reader[“user_name”]); } } } Console.ReadKey(); }
当调用层级比较多时,会出现 using 的嵌套,对影响代码的可读性,当然,当两个 using 语句中间没有其他代码时,可以这样来优化:staticvoidMain(string[] args) {
var connString = “Host=221.234.36.41;Username=gpadmin;Password=123456;Database=postgres;Port=54320”;
using (var conn = new NpgsqlConnection(connString)) { conn.Open(); using (var cmd =
new NpgsqlCommand(“select * from user_test”, conn)) using (var reader = cmd.ExecuteReader())
while (reader.Read()) Console.WriteLine(reader[“user_name”]); } Console.ReadKey(); }
使用 using 变量声明后的代码如下:staticvoidMain(string[] args) { var connString = “Host=221.234.36.41;Username=gpadmin;Password=123456;Database=postgres;Port=54320”
; usingvar conn = new NpgsqlConnection(connString); conn.Open(); usingvar cmd = new NpgsqlCommand(
“select * from user_test”, conn); usingvar reader = cmd.ExecuteReader(); while (reader.Read()) Console.WriteLine(reader[
“user_name”]); Console.ReadKey(); } Null 合并赋值这是一个很有用的语法糖,在 C# 中如果调用一个为 Null 的引用类型上的方法,会出现经典的错误:”未将对应引用到对象的实例“,所以我们在返回引用类型时,需要做些判断:
staticvoidMain(string[] args){ List list = GetUserNames(); if(list==null) {
list = new List(); } Console.WriteLine(list.Count); } publicstatic List GetUserNames() {
return null; } 在 C# 8 中可以使用 ??= 操作符更简单地实现:staticvoidMain(string[] args){ List list = GetUserNames();
list ??= new List(); Console.WriteLine(list.Count); } 当 list 为 null 时,会将右边的值分配给 list C# 9.0。
在 .NET 5 中可以使用 C# 9 ,下面是 C# 9 中几个常用的新特性initinit 是属性的一种修饰符,可以设置属性为只读,但在初始化的时候却可以指定值:publicclassUserInfo。
{ publicstring Name { get; init; } } UserInfo user = new UserInfo { Name = “oec2003” }; //当 user 初始化完了之后就不能再改变 Name 的值
user.Name = “oec2004”; 上面代码中给 Name 属性赋值会出现编译错误:
record在 C# 9 中新增了 record 修饰符,record 是一种引用类型的修饰符,使用 record 修饰的类型是一种特别的 class,一种不可变的引用类型我们创建一个名为 UserInfo 的 class ,不同的实例中即便属性值完全相同,这两个实例也是不相等的,看下面代码:。
publicclassUserInfo { publicstring Name { get; set; } } staticvoidMain(string[] args) { UserInfo user1 =
new UserInfo { Name = “oec2003” }; UserInfo user2 = new UserInfo { Name = “oec2003” }; Console.WriteLine(user1== user2);
//False } 如果使用 record ,将会看到不一样的结果,因为 record 中重写了 ==、Equals 等 ,是按照属性值的方式来进行比较的:public record UserInfo {
publicstring Name { get; set; } } staticvoidMain(string[] args) { UserInfo user1 = new UserInfo { Name =
“oec2003” }; UserInfo user2 = new UserInfo { Name = “oec2003” }; Console.WriteLine(user1== user2);
//True } 在 class 中我们经常将一个对象的实例赋值给另一个值,对赋值后的对象实例进行属性值的改变会影响到原对象实例:publicclassUserInfo { publicstring
Name { get; set; } } staticvoidMain(string[] args) { UserInfo user = new UserInfo { Name = “oec2003”
}; UserInfo user1 = user; user1.Name = “oec2004”; Console.WriteLine(user.Name); // oec2004
} 如果想要不影响原对象实例,就需要使用到深拷贝,在 record 中,可以使用 with 语法简单地达到目的:public record UserInfo { publicstring Name {
get; set; } } staticvoidMain(string[] args) { UserInfo user = new UserInfo { Name = “oec2003” }; UserInfo user1 = user with { Name=
“eoc2004”}; Console.WriteLine(user.Name); // oec2003 Console.WriteLine(user1.Name); // oec2004
} 模式匹配增强模式匹配中我觉得最有用的就是对 Null 类型的判断,在 9.0 中支持这样的写法了:publicstaticstringGetUserName(UserInfo user) {
if(user is not null) { return user.Name; } returnstring.Empty; } 顶级语句这个不知道有啥用?但挺好玩的,创建一个控制台程序,将 Program.cs 中的内容替换为下面这一行,程序也能正常运行:
System.Console.WriteLine(“HelloWorld!”); 除此之外,在 C# 8.0 和 9.0 中还有一些其他的新功能,我目前没有用到或者我觉得不太常用,就没有写在本文中了希望本文对您有所帮助。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容