C#新语法

要脑子有什么用,它只会想你。 --zhu
顶级语句(C#9.0)
1、直接在C#文件中编写入口方法的代码,不用类,不用Main。经典写法仍然支持,可以反编译了解一下。
2、同一个项目中只能有一个文件具有顶级语句。

namespace p4_1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

变成下面:

Console.WriteLine("Hello, World!");

3、顶级语句中可以直接使用await语法,也可以声明函数。

string f = await File.ReadAllTextAsync("d/1.txt");

而不用 async task

全局USING 指令(C#10.0)
1、将global修饰符添加到using前,这个命名空间就应用到整个项目,不用重复using。
2、通常创建一个专门用来编写全局using代码的C#文件。
3、如果csproj中启用了enalbe,编译器会自动隐式增加对于System、System.Linq等常用命名空间的引入,不同各类型项目引入的命名空间也不一样。

Using资源管理问题
1、复习:实现了IDisposible接口的对象可以用using进行管理。
2、问题:如果一段代码中有很多非托管资源需要被释放,代码存在多个嵌套using语句。

Using声明(C#8)
在实现了IDisposible/IAsyncDisposable接口的类型变量声明加上using,当代码执行离开变量的作用域时,对象就会被释放。

using SqlConnection conn = new SqlConnection ();

using声明陷阱

using var outStream = File.OpenWrite("e:/1.txt");
using var writer =new StreamWriter(outStream);
writer.WriteLine("hello");
string s= File.ReadAllText("e:/1.txt");
Console.WriteLine(s);

会报错文件被占用,因为两个using都没有离开作用域,不会Disposible掉。
可以写成

{
  using var outStream = File.OpenWrite("e:/1.txt");
  using var writer =new StreamWriter(outStream);
}

文件范围的命名空间声明(C#10)
1、之前版本的C#中,类型必须定义在namespace中。
2、

namespace TMS.Admin;
class Teacher
{
  public int Id{get;set;}
  public string Name{get;set;}
}

可空的引用类型(C#8)
1、复习:C#数据类型分为值类型和引用类型两种,值类型的变量不可以为空,而引用类型变量可以为空。
2、问题:如果不注意检查引用类型变量是否可空,就有可能造成程序中出现NullReferenceException异常。
3、csproj中enable启用可空引用类型检查。
4、在引用类型后添加“?”修饰符来声明这个类型是可空的。对于没有添加“?”修饰符的引用类型的变量,如果编译器发现存在为这个变量赋值null的可能性的时候,编译器会给出警告信息。

public string? Name {get;set;}

5、使用!抑制警告(不用滥用)
如果程序员确认被访问的变量、成员确实不会出现为空的情况,也可以在访问为空的变量、成员的时候加上!来抑制编译器的警告。

记录(RECORD)类型(C#9)
1、C#中的运算符默认是判断两个变量指向的是否是同一个对象,即使两个对象内容完全一样,也不相等。可以通过重写Equals方法、重写==运算符等来解决这个问题,不过需要开发人员编写非常多的额外代码。
2、在C#9.0增加了记录(record)类型的语法,编译器会为我们自动生成Equals、GetHashcode等方法。

public record Person(string FirstName,string LastName);
Person p1 = new Person(3,"张三",18);

原理探究
1、编译器会根据Person类型中的属性定义,自动为Person类型生成包含全部属性的构造方法,因此,我们编写new Person()、new Person("zhang")这两种写法都是不可以的。也会生成Tostring方法和Equals等方法。
2、通过反编译看背后原理。避record就是一个普通的类。
3、record数据类型为我们提供了为所有属性赋值的构造方法,所有属性都是只读的,而且对象可以进行值相等性比较,并且提供了可读性强的ToString()返回值。在需要编写一些不可变类并且需要进行对象值比较的对象时候,record可以帮我们把代码的编写难度大大降低。
4、可以实现部分属性只读的、而部分属性可以读写。
5、默认生成的构造方法的行为不能修改,我们可以为类型提供多个构造方法,然后其他构造方法通过this调用默认的构造方法。
6、推荐使用只读属性的类型。这样所有属性都为只读类型叫做“不可变类型“,可以让程序逻辑简单,减少并发访问、状态管理等的麻烦。

posted on 2024-07-20 22:47  小脑虎爱学习  阅读(1)  评论(0编辑  收藏  举报