(一)顶级语句(C# 9)
顶级语句是学的python这样的语言,如果是简单的控制台程序,就可以不用写命名空间、类、Main函数了,直接可以写代码。
1。直接在C# 文件中编写入口方法的代码,不用类,不用Main。经典写法仍然是支持的。反编译一下可以了解到真相
2。同一个项目中只能有一个文件具有顶级语句。
3。 顶级语句中可以直接使用await语法,也可以声明函数
Console.WriteLine($"Hello, World! {cal(1,2)}"); await File.ReadAllTextAsync("d:\\1.txt"); Console.ReadKey(); static int cal(int a,int b) { return a + b; }
4。using还是可以使用的。
把ConsoleApp1.dll拖至ILSpy窗口(注意使用8.0以上版本,否则不认识新版本c#),可以查看到反编译的结果。
可以看到类与Main函数还是有的,顶级语句编译器还是会帮助生成这些。
(二)全局Using语句(C#10)
1。将global修饰符添加到using前,这个命名空间就应用到整个项目,不用重复using.
只要你的项目中有一个文件做了global修饰,这个项目中其它全部文件就不用再重复引用这个using了。
2。通常创建一个专门用来编写全局using代码的C# 文件,类似下图:
3。如果csproj中启用了 <ImplicitUsings>enable</ImplicitUsings>,
编译器会自动隐式增加对System、System.Linq等常用命名空间的引用,不同各类型项目自动引入的命名空间也不一样。
(三)新的using声明(C# 8)
C#中,实现了IDisposible接口的对象可以使用using进行管理。
但是如果一段代码中很多托管资源需要被释放的话,代码中就会存在多个嵌套的using语句。
现在C#又嫌上面的写法太麻烦,增加了一种新方式:
在实现了IDisposable/IAsyncDisposable接口的类型变量声明前加上using,
当代码执行离开变量的作用域时,对象就会被释放。
还是上面图片的例子,现在可以这样:
当离openlib函数的作用域时,下面代码中的对象就会自动释放。
void openlib() { using SqlConnection conn=new SqlConnection(""); conn.Open(); using SqlCommand cmd=conn.CreateCommand(); cmd.CommandText="select * from T_articles"; using SqlDataReader reader=cmd.ExecuteReader(); while(reader.Read()) { string title=reader.GetString(reader.GetOrdinal("Title")); Console.WriteLine(title); } }
关于变量作用域,请再看下面的例子:
这里对象f1会被释放两次,因为它的作用域是在{} 之间。
一个坑:
见下面代码。
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);
这段代码会产生下面的异常。
原因:outStream和writer还没脱离作用域,所以还没被释放,直到运行到第四句话,报“文件被占用的错误”
解决方法:
加个大括号,定义一个作用域即可。
当然你也可以使用旧的using方式。
{ using var outStream = File.OpenWrite("m:/1.txt"); using var writer = new StreamWriter(outStream); writer.WriteLine("hello"); } string s = File.ReadAllText("m:/1.txt"); Console.WriteLine(s); Console.ReadKey();
(四)namespace和它下面的类可以是平级关系
我们定义一个类,原有方式是这样的。
表示 Class1是属于ConsoleApp1命名空间下的。
namespace ConsoleApp1 { internal class Class1 { } }
现在可以写成这样:
namespace ConsoleApp1; internal class Class1 { }
这种新写法只是去掉了大括号,你用Class1的时候,还是要写成ConsoleApp1.Class1

