当前位置: 首页 > news >正文

C#新语法

目录

顶级语句(C#9.0)

using

全局using指令(C#10.0)

using资源管理问题

using声明(C#8.0)

using声明陷阱

错误写法

正确写法

文件范围的命名空间声明(C#10.0)

可空引用类型(C#8.0)

使用

使用!抑制警告

init

record记录类型(C#9.0)

 record的原理及深入

record深入

with拷贝


顶级语句(C#9.0)

  1. 直接在C#文件中直接编写入口方法的代码,不用类,不用Main。经典写法仍然支持。
  2. 同一个项目中只能有一个文件具有顶级语句。
  3. 顶级语句中可以直接使用await语法,也可以声明函数

using

全局using指令(C#10.0)

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

using资源管理问题

实现了IDisposible接口的对象可以用using进行管理。

问题:如果一段代码中有很多非托管资源需要被释放的话,代码中就会存在着多个嵌套的using语句。

using声明(C#8.0)

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

using声明陷阱

错误写法
using var outSteam = File.OpenWrite("e:/1.txt");
using var writer = new StreamWriter(outSteam);
writer.WriteLine("Hello");
string s = File.ReadAllText("e:/1.txt");
Console.WriteLine(s);
正确写法
using (var outSteam = File.OpenWrite("e:/1.txt"))
using (var writer = new StreamWriter(outSteam))
{writer.WriteLine("Hello");
}
string s = File.ReadAllText("e:/1.txt");
Console.WriteLine(s);{using var outSteam = File.OpenWrite("e:/1.txt");using var writer = new StreamWriter(outSteam);writer.WriteLine("Hello");
}
string s = File.ReadAllText("e:/1.txt");
Console.WriteLine(s);

文件范围的命名空间声明(C#10.0)

在之前版本的C#中,类型必须定义在namespace中。

namespace NewGrammar;
class Book
{public int Id { get; set; }public string Name { get; set; }
}

可空引用类型(C#8.0)

C#数据类型分为值类型引用类型两种,值类型的变量不可以为空,而引用类型变量可以为空。

问题:如果不注意检查引用类型变量是否可空,就有可能造成程序中出现NullReferenceException异常。

使用

  1. csproj中<Nullable>enable</Nullable>启用可空引用类型检查。
  2. 在引用类型后添加“?”修饰符来声明这个类型是可空的。对于没有添加“?”修饰符的引用类型的变量,如果编译器发现存在为这个变量赋值null的可能性的时候,编译器会给出警告信息。
class Book
{public int Id { get; set; }public string? Name { get; set; }
}

使用!抑制警告

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

init

仅在对象构造期间为属性或索引器元素赋值,一旦初始化对象,将无法更改。

class Pig
{public int id { get; init; }
}

record记录类型(C#9.0)

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

namespace SelfReferecingOrganizationalStructureTree;record Book(int Id, string Name);class Program
{static void Main(string[] args){Book b1=new Book(1,"a1");Book b2=new Book(1,"a1");Book b3=new Book(2,"a1");Console.WriteLine(b1.ToString());Console.WriteLine(b1==b2);Console.WriteLine(b2==b3);Console.WriteLine(object.ReferenceEquals(b1, b2));}
}

 record的原理及深入

  1. 编译器会根据Book类型中的属性定义,自动为Book类型生成包含全部属性的构造方法。注意,默认情况下,编译器会生成一个包含所有属性的构造方法,因此,我们编写new Book()、new Book(“a1”)这两种写法都是不可以的。也会生成ToString方法和Equals等方法。
  2. 通过反编译看背后原理。避免反编译器的优化,需要把反编译器生成的代码改成C#8.0的语法。结论:record就是普通的一个类。
  3. record数据类型为我们提供了为所有属性赋值的构造方法,所有属性都是只读的,而且对象可以进行值相等性比较,并且提供了可读性强的ToString()返回值。在需要编写一些不可变类并且需要进行对象值比较的对象时候,record可以帮我们把代码的编写难度大大降低。
record深入
  1. 可以实现部分属性是只读的、而部分属性是可以读写。
    record Book(int Id, string Name)
    {public string? Author { get; set; }
    }class Program
    {static void Main(string[] args){Book b1 = new Book(1, "计算机网络");b1.Author = "小明";Console.WriteLine(b1.ToString());}
    }
  2. 默认生成的构造方法的行为不能修改,我们可以为类型提供多个构造方法,然后其他构造方法通过this调用默认的构造方法。
    record Book(int Id, string Name)
    {public string? Author { get; set; }public Book(int Id, string Name, string Author) : this(Id, Name){this.Author = Author;}
    }
  3. 也推荐使用只读属性的类型。这样的所有属性都为只读的类型叫做“不可变类型”,可以让程序逻辑简单,减少并发访问、状态管理等的麻烦。
with拷贝
  1. record也是普通类,变量的赋值是引用的传递。这是和结构体不同之处。
  2. 生成一个对象的副本,这个对象的其他属性值与原对象的相同,只有一个或者少数几个属性改变。
  3. 麻烦的做法:Book b1 = new Book(1, "计算机网络", "小明");
    用with关键字简化:Book b2 = b1 with { Id = 2, Name = "操作系统" }; 创建的也是拷贝。
static void Main(string[] args)
{Book b1 = new Book(1, "计算机网络", "小明");Book b2 = b1 with { Id = 2, Name = "操作系统" };Console.WriteLine(b1);Console.WriteLine(b2);
}

http://www.lryc.cn/news/527393.html

相关文章:

  • 微信小程序压缩图片
  • 通义灵码插件保姆级教学-IDEA(安装及使用)
  • windows下本地部署安装hadoop+scala+spark-【不需要虚拟机】
  • 倍频增量式编码器--角度插值法输出A,B(Aangular Interpolation)
  • LSM对于特殊数据的优化手段
  • 83,【7】BUUCTF WEB [MRCTF2020]你传你[特殊字符]呢
  • Go语言入门指南(二): 数据类型
  • 2025.1.26机器学习笔记:C-RNN-GAN文献阅读
  • FAST-DDS and ROS2 RQT connect
  • GESP2024年3月认证C++六级( 第三部分编程题(2)好斗的牛)
  • 记一次STM32编译生成BIN文件过大的问题(基于STM32CubeIDE)
  • 【暴力洗盘】的实战技术解读-北玻股份和三变科技
  • Day42:列表的组合
  • mantisbt添加修改用户密码
  • DroneXtract:一款针对无人机的网络安全数字取证工具
  • 简单树形菜单
  • Windows 靶机常见服务、端口及枚举工具与方法全解析:SMB、LDAP、NFS、RDP、WinRM、DNS
  • RNN实现阿尔茨海默症的诊断识别
  • 14-6-1C++STL的list
  • Redis事务机制详解与Springboot项目中的使用
  • DeepSeek-R1,用Ollama跑起来
  • Leecode刷题C语言之组合总和②
  • YOLOv8改进,YOLOv8检测头融合DynamicHead,并添加小目标检测层(四头检测),适合目标检测、分割等,全网独发
  • 【PyQt】QThread快速创建多线程任务
  • 智能码二维码的成本效益分析
  • 企业财务管理系统的需求设计和实现
  • Springboot集成Swagger和Springdoc详解
  • 类和对象(4)——多态:方法重写与动态绑定、向上转型和向下转型、多态的实现条件
  • ui-automator定位官网文档下载及使用
  • 董事会办公管理系统的需求设计和实现