C#语言简介

C#最初是微软仿照Java设计的纯面向对象应用程序开发语言,在语法、生态等各个方面都和Java有些相似。然而由于出现晚、应用场景不多、生态圈较小、国内十分冷门等各种原因,C#没什么历史包袱,一些老旧的特性、技术都会被激进的淘汰掉,于是C#的语言特性反超了Java,反倒成了Java模仿的对象。C#语言有其独特的应用场景,也非常适合在学习Java时作为补充,通过参考对比来感受这两种现代编程语言的优势。

本系列笔记使用目前最新的.Net6平台作为运行时环境,但相关的语言特性还是从最基础的早期版本开始介绍。

微软官方文档:https://learn.microsoft.com/en-us/dotnet/csharp/

提醒:C#部分微软官方文档尽量阅读英文版,中文版应该是用较为古早的翻译器机翻的,质量奇差。

.Net技术简介和历史

C#仅仅是一门语言规范,运行C#语言程序需要先将源代码编译为IL(类似Java字节码),运行IL则需要CLR运行时的支持(类似Java的HotSpotJVM)。实际上按照微软最初的设想,.Net不仅仅支持C#语言而是一个通用的平台,因此它还支持VB.Net、F#甚至出现了IronPython,但后面几种语言实在太过小众,远不如JVM生态中Kotlin、Groovy、Scala、Clojure等百花齐放的状态,因此在很多人的印象中.Net技术基本等同于C#。

按照历史发展的顺序,可以运行C#的运行时包括微软较早开发的仅支持Windows操作系统的.Net Framework,Xamarin公司(已被微软收购)开发的跨平台运行时Mono,以及微软2016年新推出的跨平台运行时.Net Core。其中,.Net Framework最终版本停留在了4.8,微软表示后续不会再继续更新该运行时,而是全面转向了.Net Core,再后来又为了展示抛弃.Net Framework全面转向.Net Core的决心,2020年微软将.Net Core改名为了.Net并发布.Net5版本,截至2021年底发布了LTS版本的.Net6

.Net Framework:最早的.Net运行时,GUI框架Winform、Web框架ASP.Net MVC等技术都广泛使用,最终版本停留在了4.8,并不再更新了。

.Net Core:微软推出的新.Net跨平台运行时,支持最新的工具和特性,老的.Net Framework包含的功能也基本迁移到了这个版本中,但并非100%完善。新版本改名为了.Net,这个名字和.Net技术的.Net在不同语境下是不同的含义,指代运行时的情境下其实就是新版本的.Net Core

.Net Standard:为了统一.Net Framework.Net CoreMono等不同的运行时,微软提出了.Net Standard作为一个通用的标准,实现了.Net Standard标准的运行时才可以称为.Net(这里指.Net技术的.Net)运行时,面向.Net Standard标准开发的程序集能够在符合对应标准的不同运行时上运行。

.Net和Java对比

前面已经介绍过,.Net(C#)和Java(包括所谓的JavaSE和JavaEE,以及后来几乎成为事实标准的Spring)是两种比较类似而且有着许多历史纠葛的开发环境。从实际使用上来看,两者确实值得对比学习。

仅从使用框架时编码的角度来说,.Net的优势是C#先进的语法以及微软官方精心设计的框架,使用感受就是两个字“丝滑”,而Java(Spring)由于受到Java落后语法的拖累以及发展较早的缘故,虽然也在追赶但还是略逊一筹;.Net缺点则是生态不如Java成熟,.Net Core虽然是开源的,但微软官方只对自家Azure云很重视,而对于其它厂商或是开源的组件基本不予理睬,导致有一些十分细节但常用的功能只有非常烂的第三方轮子,甚至无轮子可用,让人恼火,给人一种差点就完美了而功败垂成的感觉。

从实际工程角度来说,系统都是由研发团队来编码,人员肯定是流动的,团队水平必然是参差不齐的。Java比较简单,猴子都能看懂,只要整体架构不跑偏,新手小白照葫芦画瓢写写业务逻辑也问题不大,遇到问题时靠一两个老手足以“力挽狂澜”,这也就是所谓的“项目失控风险小”,Java在这一方面做的是很好的;而C#学习成本偏高,对于团队来说心智负担大,容易写出千奇百怪的代码,再加上生态不成熟,因此风险相对于Java更高。技术选型时,“心智负担”其实非常重要,C#确实是一种复杂(复杂不等同于困难)、特性较多的语言,即使是老手一段时间不接触重新开始写也得复习一下,新手就更别提了,这也是业界Java更加流行的原因之一。

其实从流行度角度来说两者差多了,在服务端开发的领域,国内互联网公司大部分都使用Java(最近也开始流行GoLang),一些要求低延时的通信、游戏等服务端也有用C++的,其余不在意Java会在GC时STW的系统基本都在转向Java的路上;确实有一些上古时期的系统采用.Net Framework开发,但新项目敢于尝试.Net Core的比较少。此外,对于C/S客户端这块,Winform还是占据主流,但都是一些古老的系统,面向的甚至是XP系统,新项目还被Electron抢走了许多份额。

从个人角度来说,如果开发一个博客之类的系统,.Net Core是个不错的选择,开发方便、部署简单,资源占用低,即使用小小的树莓派、或是512MB内存的云服务器也能运行好几个网站、数据库,Java那个让人恼火的Spring太浪费资源了,而GoLang虽然节省资源但那简陋的语法又远不能和C#相比。

那么.Net和Java究竟学习那种好呢?其实很简单,根据需求决定。对于老式Windows桌面客户端,或者Unity游戏开发,除了C#语言没有其他选择。而如果是服务端开发,以Java为主两种同时对比学习是很合适的,学习.Net Core能够吸收很多优秀的设计,作为Java的补充。

梗知识:微软起名部

微软的一些工具、产品命名有两大特点:命名特别“混乱”,而且难写难记!

.NetC#这些名字偏偏要加一个特殊字符,不仅给我的笔记系统造成了不小的问题(只能勉强写作dotNetcsharp),早期的搜索引擎也不能识别,据说这也是C#语言冷门的一大原因。

除此之外,版本号也是令人极度费解。例如Xbox 360Xbox OneXbox One X/SXbox Series X/S,还有.Net Framwork.Net Core.Net Standard.Net,看似相关,但又不同,.Net如今竟然还有两重意义。

C#开发环境搭建

在学习C#语言语法这个阶段,其实我们使用.Net Framwork或是.Net Core区别不大,但这里要注意.Net Framework仅支持Windows操作系统,而且和Visual Studio集成开发环境紧密耦合,如果你使用Linux或是不喜欢Visual Studio那是无法使用.Net Framwork的。

不过这里我们还是以最新版本的Visual Studio 2022.Net6为例进行介绍。

使用dotNet SDK命令行工具

前面已经介绍过了.Net Core是跨平台运行时,使用.Net Core自然也可以摆脱臃肿的Visual Studio集成开发环境使用其它轻量级的文本编辑器,甚至在Linux操作系统下进行开发。

安装dotnet SDK

首先要说的是,如果我们已经安装了Visual Studio 2022,那么可以直接在Visual Studio Installer程序中安装.Net开发的各种开发组件,此时就不必再单独安装dotnet SDK了。

如果我们不打算安装Visual Studio 2022,则可以在微软官网找到单独的dotnet SDK安装程序:https://dotnet.microsoft.com/en-us/download/visual-studio-sdks

安装结束后,我们可以使用如下命令输出dotnet SDK的版本信息,以查看安装是否成功。

dotnet --version

创建工程

dotnet命令行工具可以创建各种类型的工程模板,我们可以使用以下命令查看可用的模板。

dotnet new --list

这里我们可以尝试创建一个「控制台应用」,首先我们需要新建一个文件夹,然后在该文件夹中执行以下命令。

dotnet new console

此时工具为我们生成的目录结构如下。

工程根目录
  |_bin            包含编译输出的可执行文件的文件夹(编译一次后才会出现)
  |_obj            包含编译过程中的中间文件的文件夹
  |_工程名.csproj  工程构建的描述文件(类似Java工程的pom.xml)
  |_Program.cs     例子源码文件

实际上,dotnet命令行工具也支持类似Visual Studio的解决方案(sln),但这里我们出于简单起见,就直接创建工程(csproj)了。

运行以下命令可以直接编译构建并运行当前工程。

dotnet run

注:我们可以使用dotnet --help查看命令行工具的各种帮助信息。

使用Visual Studio 2022集成开发环境

如果使用Visual Studio 2022创建工程,我们需要选择创建「控制台应用」,这里尤其注意不要把.Net Core.Net Framwork工程搞混了,后者创建工程需要选择「控制台应用(.Net Framework)」。

选择后,按照提示输入解决方案名字,最后选择使用.Net6,即可创建完成。

C#版本与.Net版本对照表

实际开发中,我们首先需要选定在哪一个运行时上开发,不同的运行时支持的C#语言版本也不同,在稍老的运行时上开发可能导致一些最新的语言特性无法使用,这里我们给出一个对照表格。

C#版本 .NET版本 发布日期 特性
C# 1.0 .NET Framework 1.0 2002-02-13 委托、事件
C# 1.1 .NET Framework 1.1 2003-04-24 APM(异步编程模型)
C# 2.0 .NET Framework 2.0 2005-11-07 泛型、匿名方法、迭代器、可空类型
C# 3.0 .NET Framework 3.0 2007-11-06 隐式类型
.NET Framework 3.5 2007-11-19 对象集合初始化、自动实现属性、匿名类型、扩展方法、查询表达式、Lambda表达式、 表达式树、分部类和方法、LINQ
C# 4.0 .NET Framework 4.0 2010-04-12 动态绑定、命名和可选参数、泛型的协变和逆变、互操作性
C# 5.0 .NET Framework 4.5 2012-08-15 异步和等待(async和await)、调用方信息(Caller Information)
C# 6.0 .NET Framework 4.6 2015-07-20 静态导入、C# 6 中的新增功能
.NET Core 1.0 2016-06-27
C# 7.0 .NET Framework 4.6.2 2016-08-02 元组、C# 7.0 中的新增功能
C# 7.1 .NET Framework 4.7 2017-04-05
.NET Core 2.0 2016-08-14 .NET Core 2.0 的新增功能
C# 7.2 .NET Framework 4.7.1 2017-10-17
C# 7.3 .NET Framework 4.7.2 2018-04-30
.NET Core 2.1 2018-05-30 .NET Core 2.1 的新增功能
.NET Core 2.2 2018-12-04 .NET Core 2.2 的新增功能
C# 8.0 .NET Framework 4.8 2019-04-18 C# 8.0 中的新增功能
.NET Core 3.0 2019-09-23 .NET Core 3.0 的新增功能
.NET Core 3.1 2019-12-03 .NET Core 3.1 的新增功能
C# 9.0 .NET 5 2020-09-04 C# 9.0 中的新增功能
.NET 5 2020-10-13 What’s new in .NET 5
C# 10.0 .NET 6 2021-11-09 欢迎使用 C# 10 C# 10.0 中的新增功能
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。