盘点C# 9.0中好用的特性

  • 盘点C# 9.0中好用的特性已关闭评论
  • 140 次浏览
  • A+
所属分类:.NET技术
摘要

将类和类里面Main函数省略,只留下核心的逻辑代码就是顶级语句!1.顶级语句1


顶级语句

将类和类里面Main函数省略,只留下核心的逻辑代码就是顶级语句!

1.顶级语句1

await System.Threading.Tasks.Task.Delay(1000); System.Console.WriteLine("Hi!"); return 0; 
static class $Program {     static async Task<int> $Main(string[] args)     {         await System.Threading.Tasks.Task.Delay(1000);         System.Console.WriteLine("Hi!");         return 0;     } } 

1.顶级语句2

System.Console.WriteLine("Hi!"); return 2; 
static class $Program {     static int $Main(string[] args)     {         System.Console.WriteLine("Hi!");         return 2;     } } 

Init

struct Point {     public int X { get; }     public int Y { get; }      public Point(int x, int y)     {         this.X = x;         this.Y = y;     } } 

init通过允许调用方在构造操作过程中改变成员,访问器使不可变对象更具灵活性。 这意味着对象的不可变属性可以参与对象初始值设定项,因此不再需要类型中的所有构造函数样板。 Point类型现在只是:

struct Point {     public int X { get; init; }     public int Y { get; init; } } 

然后,使用者可以使用对象初始值设定项来创建对象。

var p = new Point() { X = 42, Y = 13 }; 

记录

记录类型是引用类型,类似于类声明。 如果不包含,记录将提供一个错误 record_base argument_list record_declaration parameter_list 。 部分记录最多只能有一个分部类型声明提供 parameter_list 。
记录参数不能 ref 使用 out 或 this 修饰符 (但 in params 允许) 。

继承

除非类为 object ,且类不能从记录继承,否则记录不能从类继承。 记录可以继承自其他记录。

 public record Student(string name,int age) {  } 
using System; using System.Collections.Generic;  public class Student : IEquatable<Student>     {         #region 属性这部分 可以看到set属性没有         #记录具有不可变性,记录一旦初始化完成,那么它的属性值将不可修改(可以通过反射修改)         public string Name { get; init; }         public int Age { get; init; }         #endregion          #region         protected virtual Type EqualityContract => typeof(Student);         #endregion                public override bool Equals(object? obj) => Equals(obj as R1);         public virtual bool Equals(Student? other)         {             return !(other is null) &&                 EqualityContract == other.EqualityContract &&                                  EqualityComparer<string>.Default.Equals(this.Name, other.Name) &&                 EqualityComparer<int>.Default.Equals(this.Age, other.Age);         }         public static bool operator ==(R1? left, R1? right)             => (object)left == right || (left?.Equals(right) ?? false);         public static bool operator !=(R1? left, R1? right)             => !(left == right);           public override string ToString()         {             StringBuilder builder = new StringBuilder();             builder.Append("Student");             builder.Append(" { ");             if (this.PrintMembers(builder))             {                 builder.Append(" ");             }             builder.Append("}");             return builder.ToString();         }     } 

支持解构

public record Student(string Name, int Age) {         public string Name { get; set; }         public int Age { get; set; } } 
Student record = new Student("张三",19) ; var (name, age) = record;  ==》这个可以用在switch匹配上 还记得我们 string value = record switch{                 ("张三", 19) => "01",                 ("李四", 25) => "02",                 _ => "default"  };  ## 之所以可以用这个这么用 是因为编译后多了这样的解构函数  public void Deconstruct(out string Name, out int Age) => (Name, Age) = (this.Name, this.Age); 

with 表达式

with表达式是使用以下语法的新表达式。

Student record2  = record with { Name = "王五" };  //在编译后等价于 var temp = record.<Clone>$(); temp.Name = "王五"; record2 = temp;  //不赋值 完全克隆 Student record3  = record with { }; 

好处:

1.比较两个属性是否相等跟属性设置的顺序无关
2.方便快速克隆,不影响原数据
3.补充了结构体不支持继承以及性能不高的短处

Lambda 弃元参数

允许丢弃 (用作 _ lambda 和匿名方法的参数) 。 例如:

  • lambda: (_, _) => 0 , (int _, int _) => 0
  • 匿名方法: delegate(int _, int _)
public delegate void FuncA(string a, string c);          static void Main(string[] args)         {              FuncA func = (_, _) => { };          }