快速开始
.NET 平台 和 C#语言
C#(CSharp) 是一种编程语言, 而 .NET 是一个开发平台(运行时 + 标准库 + 工具链)
.NET 平台 是 C# 语言 的开发运行环境。 也可以运行其它编程语言,比如 F#、VB.NET、IronPython 等等。但是目前主流都是用 C# 语言开发。
这里面 :
🔸 运行时(英文为 CLR)负责加载和执行 C# 代码
🔸 标准库(BCL)提供了大量的现成代码,方便我们开发各种功能。
🔸 工具链 包括编译器、打包工具、调试器等,帮助我们编写、编译、调试和发布 C# 程序。
如果说 C# 是车,那 .NET 是就是公路系统,它们紧密相关。
.NET 平台 的历史可以大致分为三个主要时代:
-
.NET Framework时代这是 .NET 的起点,是 最初 的、 仅限 Windows 的、 闭源 的 实现,
-
.NET Core时代为了适应云原生和跨平台的需求,2017 年 微软从头开始构建了一个全新的
.NET Core。这是一个 全新 的、 跨平台 的、 开源 的 重写版本。
这时候,就有
.NET Framework和.NET Core2 种平台,各自发展,推出各自的新版本。 -
.NET时代后来,微软不想再让开发者面对2个并行、名字混乱的 .NET 平台, 想“只有一个 .NET”。
从2020 年 11 月 开始,直接推出
.NET 5。从这个版本开始,不再有 "Core" 或 "Framework" 的后缀,只有一个统一的
.NET平台。 发布周期固定为每年 11 月发布一个新主版本。此时,
.NET Core的版本 为3.1,就是它的最后版本了。.NET Framework的版本 为4.8,2022年最后推出4.8.1。 后面可能会有安全补丁,不会再有新功能了。可以说
.NET完全替代了.NET core。 但是.NET Framework由于是预装在 Windows系统里面的,有时为了安装使用程序方便,还会使用它。
C#语言 和 .NET 平台 的 历史版本 对应关系 如下
| 版本 | 发布年份 | .NET 平台 (首次引入) | 关键特性 |
|---|---|---|---|
| C# 1.0 | 2002 | .NET Framework 1.0 | 基础的面向对象特性(类, 结构, 接口, 继承等), 委托, 事件, 属性, unsafe |
| C# 2.0 | 2005 | .NET Framework 2.0 | 泛型 (Generics), 分部类型 (Partial types), 匿名方法, 可空类型 (Nullable types), 迭代器 (yield) |
| C# 3.0 | 2007 | .NET Framework 3.5 | LINQ (语言集成查询), Lambda 表达式, 扩展方法, 匿名类型, 自动属性, var 关键字 |
| C# 4.0 | 2010 | .NET Framework 4.0 | 动态绑定 (dynamic), 命名参数和可选参数, 泛型协变和逆变 |
| C# 5.0 | 2012 | .NET Framework 4.5 | 异步编程模型 (async/ await), 调用方信息特性 (Caller Info Attributes) |
| C# 6.0 | 2015 | .NET Framework 4.6 | Roslyn 编译器, 字符串内插, nameof, Null 条件运算符 (?.), 表达式体成员, using static |
| C# 7.0 | 2017 | .NET Framework 4.7 / .NET Core 1.0 | 元组 (Tuples), 模式匹配 (is, switch), out 变量, 本地函数, ref 返回和 ref 局部变量 |
| C# 7.1 | 2017 | .NET Core 2.0 | async Main 方法, default 字面量表达式, 推断的元组元素名称 |
| C# 7.2 | 2017 | .NET Core 2.0 | Span |
| C# 7.3 | 2018 | .NET Core 2.1 / .NET Framework 4.8 | 元组相等性比较, stackalloc 改进, 表达式变量用于更多位置 |
| C# 8.0 | 2019 | .NET Core 3.0 | 可空引用类型, 异步流 (IAsyncEnumerable<T>), 接口的默认实现, switch 表达式, using 声明 |
| C# 9.0 | 2020 | .NET 5 | 记录类型 (record), 顶级语句 (Top-level statements), init-only 属性, 改进的模式匹配 |
| C# 10 | 2021 | .NET 6 | 全局 using 指令 (global using), 文件范围的命名空间, record struct, const 字符串内插 |
| C# 11 | 2022 | .NET 7 | 泛型数学接口, 必需成员 (required), file-local 类型, 原始字符串字面量 ("""...""") |
| C# 12 | 2023 | .NET 8 | 主构造函数 (Primary Constructors), 集合表达式, using 别名指令可用于任何类型, ref readonly 参数 |
| C# 13 | 2024 | .NET 9 | 参数关键字的默认值(params collections 默认值), 扩展属性模式(ref 扩展属性模式), 锁对象(lock 对象), 反射中的拦截器(reflection 拦截器), 改进的模式匹配(改善的模式匹配), 别名(aliases) |
| C# 14 | 2025 | .NET 10 | 文件基础应用(file-based apps,支持单文件 C# 脚本和实用工具), 改进的模式匹配和表达式(改进的模式匹配和表达式), 字段主构造函数(field primary constructors), 部分属性(partial properties), WebAssembly 支持增强(WebAssembly 增强) |
安装
安装使用 .NET 和 C#, 主要是 安装 .NET SDK 和 IDE 开发环境软件。
Windows 平台上, 最典型的做法就是安装 Visual Studio IDE,安装过程中,同时选择相应的 .NET 开发组件,参考这里
其实,很多时候,我们并不需要 Visual Studio。 除非某些 必须在Windows上的开发场景, 比如 开发一写Windows图形界面软件 需要用 Visual Studio里面的 Windows 窗体设计师、WPF 设计师、WinUI 设计师 和 图形化调试器、性能分析工具。
这个系列教程重点在学习 C# 语言本身,而且有些学员用的是苹果电脑不方便安装 Visual Studio,所以我们使用跨平台的开发方案: VS Code IDE 和 .NET SDK
安装 .NET SDK
点击这里到.NET官网, 点击 下载 .NET SDK 按钮, 然后安装
注意: 这里安装的是 .NET SDK(开发工具包), 而不是 .NET Runtime(运行环境)。
🔸.NET SDK
包含了 .NET Runtime, 以及 编译器、工具链等开发工具。
这是开发者必须安装的。
🔹.NET Runtime
只用来运行已经编译好的程序, 不包含开发工具。
你可以大体看作是 .NET Runtime = CLR(语言引擎) + BCL(标准库)。
这是有时候用户需要安装的。
为什么说有时候呢? 因为我们也可以编译出不需要安装 .NET Runtime 就能运行的程序,后面会讲到。
安装 VS Code IDE
点击这里,到 VS Code 官网,下载安装好 VS Code
然后点击最左侧 Activity Bar 上的 扩展 图标,搜索安装 C# Dev Kit 。 这个扩展 包含了 C# 语言的语法高亮、代码补全、调试支持等功能。
快速开始
开发的 C# 程序,通常需要新建项目,对应一个项目目录,里面除了有代码文件, 还包括项目的配置文件,资源文件等等
为了集中精力在了解编程语言本身,我们先开发最容易理解的 控制台应用程序。
控制台应用程序 让用户操作的界面是 命令行窗口,而不是图形界面。
创建项目目录
进入到项目上层目录,打开一个命令行窗口,执行命令 dotnet new console -n <项目目录名> , 比如
dotnet new console -n Hello
就会创建名为 Hello 的项目目录 和 模板文件。
如果不指定-n 参数,直接 dotnet new console 就会以当前目录为项目目录,目录名为项目名称,只创建模板文件在当前目录中。
其中 console 指定了项目类型(模板), 可以用命令 dotnet new list 查看有哪些类型模板,比如
>dotnet new list
这些模板已匹配你的输入:
模板名 短名称 语言 标记
--------------------------------------- -------------------------- ---------- ----------------------------------
API 控制器 apicontroller [C#] Web/ASP.NET
ASP.NET Core gRPC 服务 grpc [C#] Web/gRPC/API/Service
ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service
ASP.NET Core Web API (native AOT) webapiaot [C#] Web/Web API/API/Service
ASP.NET Core Web 应用 webapp,razor [C#] Web/MVC/Razor Pages
ASP.NET Core Web 应用(模型-视图-控制器) mvc [C#],F# Web/MVC
ASP.NET Core 空 web [C#],F# Web/Empty
Dotnet 本地工具清单文件 tool-manifest Config
EditorConfig 文件 editorconfig,.editorconfig Config
Windows 窗体应用 winforms [C#],VB Common/WinForms
Windows 窗体控件库 winformscontrollib [C#],VB Common/WinForms
Windows 窗体类库 winformslib [C#],VB Common/WinForms
WPF 应用程序 wpf [C#],VB Common/WPF
WPF 用户控件库 wpfusercontrollib [C#],VB Common/WPF
WPF 类库 wpflib [C#],VB Common/WPF
WPF 自定义控件库 wpfcustomcontrollib [C#],VB Common/WPF
控制台应用 console [C#],F#,VB Common/Console
类库 classlib [C#],F#,VB Common/Library
解决方案文件 sln,solution Solution
辅助角色服务 worker [C#],F# Common/Worker/Web
编写代码,本地运行
然后用 vscode 打开这个目录,你会发现里面有一个代码文件 Program.cs。
这就是 C# 程序的代码文件, 扩展名为 cs。
我们修改的代码为
Console.WriteLine("Hello, 白月黑羽!");
然后点击 vscode 里面的运行按钮,就可以编译运行该项目代码了。
编译产生的可执行程序在 bin\Debug\net<版本号> 目录下
这是一个开发者调试版本的程序,依赖本地安装的 .NET 运行环境 。
✳️ dotnet run 命令
如果你使用其它的IDE,没有运行按钮,也可以在命令行窗口,进入项目根目录,执行如下命令来编译运行代码。
dotnet run
运行它,其实会先执行 dotnet build 编译代码,然后运行编译产生的可执行程序。
✳️ 跳过构建,直接运行已构建的产物
如果你确定代码没有修改,想直接运行上次编译好的程序,可以使用 --no-build 参数,跳过构建步骤,直接运行上次编译好的产物:
dotnet run --no-build
发布程序
将来我们开发各种程序完成后,如果要拷贝给别人使用。
如果别人的电脑上已经安装了 .NET 运行环境,就可以直接拷贝 bin\Debug\net<版本号> 目录下的可执行程序给别人运行。
如果别人的电脑上没有安装 .NET 运行环境,就需要发布出一个可以独立运行的发布版 可执行程序。
新建一个 release.bat 文件(苹果电脑可以叫 release.sh) , 里面是如下内容
dotnet publish -c Release --self-contained true -p:PublishTrimmed=true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:DebugType=None -p:StripSymbols=true -p:EnableCompressionInSingleFile=true
这些参数什么意思,后面的章节会详细讲解。
运行后,产生的可执行文件在 bin\Release\net10.0\win-x64\publish 目录中,可以拷贝给别人运行该文件。
这个可执行程序里面内嵌了一个 .NET 运行环境,所以可执行程序体积有些大,大约 10M 左右
发布 Native AOT 程序
现在的 .NET 编译时支持 Native AOT 编译(提前编译)。
可以简单理解为 连 内嵌.NET 运行环境 都不需要了,就像 C 语言的程序编译出来的代码一样。
一旦你开启 Native AOT(提前编译),单 exe 体积会直接「腰斩甚至砍到脚」,很多真实项目能从 30~40 MB 直接降到 3~10 MB,这就是 当前最硬核的体积压缩方式。
而且启动更快。
新建一个 aot.bat 文件(苹果电脑可以叫 aot.sh) , 里面是如下内容
dotnet publish -c Release --self-contained true -p:PublishAot=true -p:DebugType=None -p:StripSymbols=true
运行后,产生的可执行文件也在 bin\Release\net10.0\win-x64\publish 目录中,可以拷贝给别人运行该文件。
这个可执行程序里面没有内嵌了 .NET 运行环境,所以可执行程序体积很小,大约 1M 左右
当然不是所有的 .NET 程序都可以 这样编译的。典型的是 代码里面用了反射(Reflection.Emit),动态加载 程序集,和使用某些不兼容AOT的第三方库。
语句
在 C# 语言中,语句 是构成程序的基本单位。
一个语句通常表示一个完整的操作或指令,告诉计算机执行某个具体的任务。
例如,下面的代码行就是一个语句:
Console.WriteLine("Hello, 白月黑羽!");
关于 Console.WriteLine 具体的解释, 在后面的章节会有详细的学习。
这里我们只要知道 Console.WriteLine(xxx) 这样写,就可以让计算机在屏幕上显示括号里面的内容即可。
有时候一个语句就是一行,但也可以跨多行书写,只要符合语法规则即可。
比如,下面的语句虽然分成了两行,但它们共同构成了一个完整的语句:
Console.WriteLine(
"Hello, 白月黑羽!"
);
语句的结尾通常以分号 ; 结束,表示该语句的结束。
当然也有不需要加分号的语句,后面会学到。
注释
虽然 C# 的语法很清晰,但我们写的代码为了别人容易看懂,甚至自己以后能看懂,就需要加入一些我们熟悉的 人话,也就是人类语言,辅助理解。
这些辅助理解的人话,就是注释。
C#的注释有两种主要形式:
- 单行注释: 以
//开头,从//到该行末尾的内容都是注释。 - 多行注释: 以
/*开头,以*/结尾,之间的所有内容都是注释。
比如
// info 变量记录作者的信息,包括名字和身高
var info = new Dictionary<string, string>{
{"name", "黑羽白月"},
{"height", "180cm"}
};
// 改变作者的身高记录
info["height"] = "175cm";
Console.WriteLine(info["height"]); // 打印身高到屏幕上
怎么样,有了上面的注释,这些代码是不是更容易读懂了?
我们要注意的是,注释不会对代码的执行有任何影响。
多行注释的例子:
/*
info 变量 记录 作者的信息
包括 名字,身高,体重
*/
var info = new Dictionary<string, string>()
{
{"name", "黑羽白月"},
{"height", "180cm"}
};
顶级语句
前面的示例代码文件里面的内容,很简单
// Program.cs 整个文件就这几行
Console.WriteLine("Hello, 白月黑羽!");
这种写法称之为 : Top-level statements(顶级语句)
这是 C# 9(.NET 5)开始引入的超级好用的语法特性, 从 C# 12(.NET 8)开始几乎所有新项目默认就是这种写法。
在这之前,你必须得定义一个包含 Main 方法的类, 像这样:
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, 白月黑羽!");
}
}
现在只需要使用顶级语句简写, 编译器在背后自动帮你生成了类似的代码。
这样写起来更快捷。
如果你项目中有多个文件的话,缺省只允许一个文件里面使用顶级语句。
因为顶级语句所在的文件就是 整个程序的入口。 入口,只能有一个。