• 2.1C#新语法


    .net Core重难点知识

    C#新语法

    顶级语句

    之前必须有类和类中的Main方法,从C#9.0开始,可以直接在C#文件中编写入口代码,不需要再声明类和方法

    //之前的方法
    	internal class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello, World!");
            }
        }
    //顶级语句
    	Console.WriteLine("Hello, World!");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    一个项目中只能有一个文件具有顶级语句

    全局using指令

    有些类库在多个文件中都会引用,使用全局using指令可以只写一遍则项目中所有的源码都可以使用了,通常将全局using指令单独写一个C#文件。

    global using Mircrosoft.Data.Sqlite;
    global using System.Text.Json;
    
    • 1
    • 2

    另外,在csproj文件中加入enable编译器会根据项目类型自动隐式加上System等常用明明空间的引入。

    using声明

    //旧的using释放资源,里面有多重嵌套
    using (var conn = new SqlConnection(connStr))
    {
        conn.Open();
        using (var cmd = conn.CreateCommand())
        {
            cmd.CommandText = "select * from T_Articles";
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    C#8以后,可以使用using声明如果类型实现了IDisposable或者IAsyncDisposable接口,则当代码离开using声明的变量作用域的时候,自动调用Dispose方法。

    using System.Data.SqlClient;
    string connStr = "Data Source=.;Initial Catalog=demo1;Integrated Security=True";
    
    using var conn = new SqlConnection(connStr);
    conn.Open();
    using var cmd = conn.CreateCommand();
    cmd.CommandText = "select * from T_Articles";
    using var reader = cmd.ExecuteReader();
    while (reader.Read())
    {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    要注意使用的时机

    //以下是有问题的代码
    /*
    using var outStream = File.OpenWrite("e:/1.txt");
    using var writer = new StreamWriter(outStream);
    writer.WriteLine("hello");
    string s = File.ReadAllText("e:/1.txt"); //这句会报错,因为此时1.txt仍然被outStream占用
    Console.WriteLine(s);*/
    {
        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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    简化命名空间声明

    之前版本,类必须在命名空间中

    namespace ConsoleApp2
    {
        class Program
        {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在C#10之后,可以不再使用{},文件中所有的类型都是这个命名空间下的成员

    namespace TMS.Admin;
    class Teacher
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可空类型

    在引用类型后面加上?表示该变量是可以为null

    在使用该变量后,vs会给出警告“解引用可能出现空引用”

    如果确定变量不会为空,则可以使用!抑制编译器的警告person.number!.ToLower(),但是尽量少用

    记录类型

    如果两个对象为同一类型,并且属性完全相等,但是他们为不同的对象,使用==比较的话会返回false,可以通过重写Equals、==等来解决,但是比较麻烦。

    C#9.0新增记录(record)类型,自动生成Equals,GetHashcode,ToString等方法。

    public record Person(string FirstName, string LastName);

    编译器会根据Person中的属性定义(括号中),自动生成包含全部属性的构造方法。此时使用new Person()/new Person("张三")是错误的,但是所有的属性是只读的。

    Person p1 = new Person("Zack", "Yang");
    Person p2 = new Person("Zack", "Yang");
    Console.WriteLine(p1);//Person { FirstName = Zack, LastName = Yang }
    Console.WriteLine(p1 == p2);// true 此时比较的是两个对象的属性值
    
    • 1
    • 2
    • 3
    • 4

    定义部分属性可读可写

    public record Person(string LastName)
    {
        public string FirstName { get; set; }
        public void SayHello()
        {
            Console.WriteLine($"Hello,我是{LastName} {FirstName}");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    此时LastName仍然是自动生成的可读属性。新建实例:Person s = new Person("y")

    提供多个构造函数

    public record User(string UserName, string? Email, int Age)
    {
        public User(string userName, int age)
            : this(userName, null, age){ }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 编译器会自动生成包含这3个属性的构造方法
    2. 自己可以自定义其他的构造方法

    总结:recode总是默认生成包含全部属性的构造函数,且属性是只读的

    创建副本

    User u1 = new User("a","b",19);
    User u2 = new User(u1.userName,"c",20);//可以使用这种方法
    User u3 = u1 with(Email="test@qq.com");//推荐
    
    • 1
    • 2
    • 3
  • 相关阅读:
    多要素气象站:自动观测、数据可查
    美国隐私安全人工智能大模型公司【Fantix】160万美元融资
    一个奇葩的线上问题,导致我排查了一天!
    用jQuery向FCKEditor插件取值、赋值
    软件过程与建模学习之:Ethics, ACs Code Ethics, IEEE Code of Ethics
    分析 验证码处理servlet的逻辑
    报白是什么意思?入驻抖音小店哪些类目需要报白?报白如何操作?
    国际化配置(ant-design-vue设置成中文)
    c++用dijkstra堆优化版求严格次短路(洛谷p2865)acwing(Tle)版本
    Scala基础教程--14--隐式转换
  • 原文地址:https://blog.csdn.net/weixin_44064908/article/details/126231242