C#语言介绍 2021/3/9·· Edit Online C#(读作" See Sharp")是一种新式编程语言,不仅面向对象,还类型安全。开发人员利用C#能够生成在NET生 态系统中运行的多种安全可靠的应用程序。C#源于C语言系列,C、C++、Java和 JavaScript程序员很快就可以 上手使用。本教程概述了C#8及更高版本中该语营的主要组件。如果想要通过交互式示例探索语营,请尝试 C#简介教程 C#是面向对象的、面向组件的编程语营。C#提供了语营构造来直接支持这些概念,让C#成为一种非常自然的 语营,可用于创建和使用软件组件。自诞生之日起,C#就添加了支持新工作负载和新兴软件设计实践的功能 多项C#功能有助于创建可靠且持久的应用程序。垃圾回收*自动回收不可访问的未用对象所占用的内存。可以 为nu的类型可防范不引用已分配对象的变量。异常处理提供了一种结构化且可扩展的方法来进行错误检测和 恢复。 Lambda表达式支持函数编程技术。语营集成查询(LNo语法创建一个公共模式,用于处理来自任何源 的数据。异步操作语营支持提供用于构建分布式系统的语法。C#有统一类型系统*。所有C#类型(包括int和 double等基元类型)均继承自一个根ojet类型。所有类型共用一组通用运算。任何类型的值都可以一致地 进行存储、传输和处理。此外,C#还支持用户定义的引用类型和值类型。C#允许动态分配轻型结构的对象和内 嵌存储。C#支持泛型方法和类型,因此增强了类型安全性和性能。C#可提供迭代器,使集合类的实现者可以定 义客户端代码的自定义行为。 C#强调版本控制,以确保程序和库以兼容方式随时间推移而变化。℃#设计中受版本控制加强直接影响的方面 包括:单独的 virtual和 override修饰符,关于方法重载决策的规则,以及对显式接口成员声明的支持。 NET体系结构 C#程序在NET上运行,而NET是名为公共语言运行时(CLR)的虛执行系统和一组类库。CLR是 Microsoft对公 共语言基础结构(CL)国际标准的实现。C凵是创建执行和开发环境的基础,语言和库可以在其中无缝地协同工 用C#编写的源代码被编译成符合C凵规范的中间语(。l代码和资源(如位图和字符串)存储在扩展名通常 为d的程序集中。程序集包含一个介绍程序集的类型、版本和区域性的清单 执行C#程序时,程序集捋加载到CLR。CLR会直接执行实时(Jm编译,将‖代码转换成本机指合。CLR可提供 其他与自动垃圾回收、异常处理和资源管理相关的服务。CLR执行的代码有时称为"托管代码"(而不是"非托管代 码"),被编译成面向特定平台的本机语营。 语营互操作性是NET的一项重要功能。C#编译器生成的‖代码符合公共类型规范(CTS)。通过C#生成的l 代码可以与通过NET版本的F#、 Visua| Basic、C++或其他20多种与CTS兼容的任何语营所生成的代码进行交 互。一个程序集可能包含多个用不同NET语营编写的模块,且类型可以相互引用,就像是用同一种语营编写的 除了运行时服务之外,NET还包含大量库。这些库支持多种不同的工作负载。它们已整理到命名空间中,这些命 名空间提供各种实用功能,包括文件输入输出、字符串控制、XML分析、Web应用程序框架和 Windows窗体控 件。典型的C#应用程序广泛使用NET类库来处理常见的"管道"霁碎工作。 有关NET的详细信息,请参阅NET概述。 Hello world " Hello, World"程序历来都用于介绍编程语言。下面展示了此程序的C#代码:
C# 语⾔介绍 2021/3/9 • • Edit Online .NET 体系结构 Hello world C#(读作“SeeSharp”)是一种新式编程语言,不仅面向对象,还类型安全。 开发人员利用 C# 能够生成在 .NET 生 态系统中运行的多种安全可靠的应用程序。 C# 源于 C 语言系列,C、C++、Java 和 JavaScript 程序员很快就可以 上手使用。 本教程概述了 C# 8 及更高版本中该语言的主要组件。 如果想要通过交互式示例探索语言,请尝试 C# 简介教程。 C# 是面向对象的、面向组件的编程语言。 C# 提供了语言构造来直接支持这些概念,让 C# 成为一种非常自然的 语言,可用于创建和使用软件组件。 自诞生之日起,C# 就添加了支持新工作负载和新兴软件设计实践的功能。 多项 C# 功能有助于创建可靠且持久的应用程序。 垃圾回收*自动回收不可访问的未用对象所占用的内存。 可以 为 null 的类型可防范不引用已分配对象的变量。 异常处理提供了一种结构化且可扩展的方法来进行错误检测和 恢复。 Lambda 表达式支持函数编程技术。 语言集成查询 (LINQ) 语法创建一个公共模式,用于处理来自任何源 的数据。 异步操作语言支持提供用于构建分布式系统的语法。 C# 有统一类型系统*。 所有 C# 类型(包括 int 和 double 等基元类型)均继承自一个根 object 类型。 所有类型共用一组通用运算。 任何类型的值都可以一致地 进行存储、传输和处理。 此外,C# 还支持用户定义的引用类型和值类型。 C# 允许动态分配轻型结构的对象和内 嵌存储。 C# 支持泛型方法和类型,因此增强了类型安全性和性能。 C# 可提供迭代器,使集合类的实现者可以定 义客户端代码的自定义行为。 C# 强调版本控制,以确保程序和库以兼容方式随时间推移而变化。 C# 设计中受版本控制加强直接影响的方面 包括:单独的 virtual 和 override 修饰符,关于方法重载决策的规则,以及对显式接口成员声明的支持。 C# 程序在 .NET 上运行,而 .NET 是名为公共语言运行时 (CLR) 的虚执行系统和一组类库。 CLR 是 Microsoft 对公 共语言基础结构 (CLI) 国际标准的实现。 CLI 是创建执行和开发环境的基础,语言和库可以在其中无缝地协同工 作。 用 C# 编写的源代码被编译成符合 CLI 规范的中间语言 (IL)。 IL 代码和资源(如位图和字符串)存储在扩展名通常 为 .dll 的程序集中。 程序集包含一个介绍程序集的类型、版本和区域性的清单。 执行 C# 程序时,程序集将加载到 CLR。 CLR 会直接执行实时 (JIT) 编译,将 IL 代码转换成本机指令。 CLR 可提供 其他与自动垃圾回收、异常处理和资源管理相关的服务。 CLR 执行的代码有时称为“托管代码”(而不是“非托管代 码”),被编译成面向特定平台的本机语言。 语言互操作性是 .NET 的一项重要功能。 C# 编译器生成的 IL 代码符合公共类型规范 (CTS)。 通过 C# 生成的 IL 代码可以与通过 .NET 版本的 F#、Visual Basic、C++ 或其他 20 多种与 CTS 兼容的任何语言所生成的代码进行交 互。 一个程序集可能包含多个用不同 .NET 语言编写的模块,且类型可以相互引用,就像是用同一种语言编写的 一样。 除了运行时服务之外,.NET 还包含大量库。 这些库支持多种不同的工作负载。 它们已整理到命名空间中,这些命 名空间提供各种实用功能,包括文件输入输出、字符串控制、XML 分析、Web 应用程序框架和 Windows 窗体控 件。 典型的 C# 应用程序广泛使用 .NET 类库来处理常见的“管道”零碎工作。 有关 .NET 的详细信息,请参阅 .NET 概述。 “Hello,World”程序历来都用于介绍编程语言。 下面展示了此程序的 C# 代码:
using System class Hello static void Main() Console. WriteLine("Hello, World"); Hel, World"程序始于引用 System命名空间的 using指命。命名空间提供了一种用于组织C#程序和库的分 层方法。命名空间包含类型和其他命名空间。例如, System命名空间包含许多类型(如程序中引用的 Console 类)和其他许多命名空间(如I0和 Collections)。借助引用给定命名空间的 using指合,可以非限定的方式 使用作为相应命名空间成员的类型。由于使用ui指合,因此程序可以使用 Console.WriteLine作为 System. Console. WriteLine "Hll,Wd程序声明的Ho类只有一个成员,即hain方法。ain方法使用stic修饰符进行声明。 实例方法可以使用关键字tis引用特定的封闭对象实例,而静态方法则可以在不引用特定对象的情况下运行 按照约定,Nain静态方法是C#程序的入囗点。 程序的输出是由 System命名空间中osle类的 WriteLine法生成。此类由标准类库提供。默认情况下 编译器会自动引用标准类库。 类型和变量 C#有两种类型:值类型和引用类型。值类型的变量直接包含它们的数据。引用类型的变量存储对数据(称为对 象")的引用。对于引用类型,两个变量可以引用同一个对象;对一个变量执行的运算可能会影响另一个变量引用 的对象。借助值类型,每个变量都有自己的数据副本;因此,对一个变量执行的运算不会影响另一个变量(ref 和out参数变量除外)。 标识符为变量名称。标识符是不包含任何空格的 unicode字符序列。如果标识符的前缀为@,则该标识符可以 是C#保留字。在与其他语营交互时,使用保留字作为标识符很有用。 C#的值类型进一步分为:简单类型、枚举类型、结构类型、可以为nu的值类型和元组值类型。C#引用类型又 细分为类类型、接口类型、数组类型和委托类型。 以下大纲概述了C#的类型系统。 ●值类型 o简单类型 有符号整型: sbyte、 short、int、1ong 无符号整型:byte、 ushort、uint、 ulong o Unicode字符:char,表示UTF16代码单元 0EE二进制浮点: float、 double o高精度十进制浮点数: decima 布尔值:bol,表示布尔值(true或 枚举类型 genomE(…)格式的用户定义类型。emum类型是一种包含已命名常量的独特类型。每个 um类型都有一个基础类型(必须是八种整型类型之一)。eum类型的值集与基础类型的值 集相同 结构类型 格式为 struct s{}的用户定义类型 可以为nu的值类型 值为mu的其他所有值类型的扩展
using System; class Hello { static void Main() { Console.WriteLine("Hello, World"); } } 类型和变量 “Hello,World”程序始于引用 System 命名空间的 using 指令。 命名空间提供了一种用于组织 C# 程序和库的分 层方法。 命名空间包含类型和其他命名空间。例如, System 命名空间包含许多类型(如程序中引用的 Console 类)和其他许多命名空间(如 IO 和 Collections )。 借助引用给定命名空间的 using 指令,可以非限定的方式 使用作为相应命名空间成员的类型。 由于使用 using 指令,因此程序可以使用 Console.WriteLine 作为 System.Console.WriteLine 的简写。 “Hello,World”程序声明的 Hello 类只有一个成员,即 Main 方法。 Main 方法使用 static 修饰符进行声明。 实例方法可以使用关键字 this 引用特定的封闭对象实例,而静态方法则可以在不引用特定对象的情况下运行。 按照约定, Main 静态方法是 C# 程序的入口点。 程序的输出是由 System 命名空间中 Console 类的 WriteLine 方法生成。 此类由标准类库提供。默认情况下, 编译器会自动引用标准类库。 C# 有两种类型:值类型 和 引用类型。 值类型的变量直接包含它们的数据。 引用类型的变量存储对数据(称为“对 象”)的引用。 对于引用类型,两个变量可以引用同一个对象;对一个变量执行的运算可能会影响另一个变量引用 的对象。 借助值类型,每个变量都有自己的数据副本;因此,对一个变量执行的运算不会影响另一个变量( ref 和 out 参数变量除外)。 标识符为变量名称。 标识符是不包含任何空格的 unicode 字符序列。 如果标识符的前缀为 @ ,则该标识符可以 是 C# 保留字。 在与其他语言交互时,使用保留字作为标识符很有用。 C# 的值类型进一步分为:简单类型、枚举类型、结构类型、可以为 null 的值类型和元组值类型。 C# 引用类型又 细分为类类型、接口类型、数组类型和委托类型。 以下大纲概述了 C# 的类型系统。 值类型 简单类型 枚举类型 结构类型 可以为 null 的值类型 有符号整型: sbyte 、 short 、 int 、 long 无符号整型: byte 、 ushort 、 uint 、 ulong Unicode 字符: char ,表示 UTF-16 代码单元 IEEE 二进制浮点: float 、 double 高精度十进制浮点数: decimal 布尔值: bool ,表示布尔值( true 或 false ) enum E {...} 格式的用户定义类型。 enum 类型是一种包含已命名常量的独特类型。 每个 enum 类型都有一个基础类型(必须是八种整型类型之一)。 enum 类型的值集与基础类型的值 集相同。 格式为 struct S {...} 的用户定义类型 值为 null 的其他所有值类型的扩展
o元组值类型 o格式为(T1,m2,)的用户定义类型 ●引用类型 o类类型 o其他所有类型的最终基类: object o Unicode字符串: strin,表示UTF-16代码单元序列 格式为 class C.)}的用户定义类型 接口类型 o格式为 interface I.}的用户定义类型 数组类型 0一维、多维和交错。例如:intn、t,1和intn o委托类型 o格式为 delegate int D(.)的用户定义类型 C#程序使用类型声明创建新类型。类型声明指定新类型的名称和成员。用户可定义以下六种C#类型:类类 型、结构类型、接口类型、枚举类型、委托类型和元组值类型。 class类型定义包含数据成员(字段)和函数成员(方法、属性及其他)的数据结构。类类型支持单一继承和多 形性,即派生类可以扩展和专门针对基类的机制。 ·strt类型定义包含数据成员和函数成员的结构,这一点与类类型相似。不过,与类不同的是,结构是值类 型,通常不需要进行堆分配。结构类型不支持用户指定的继承.并且所有结构类型均隐式继承自类型 object · interface类型将协定定义为一组已命名的公共成员。实现 interface的las或strt必须提供接口 成员的实现代码。 interface可以继承自多个基接口,clas和 struct可以实现多个接口。 ● delegate类型表示引用包含特定参数列表和返回类型的方法。通过委托,可以将方法视为可分配给变量并 可作为参数传递的实体。委托类同于函数式语营提供的函数类型。它们还类似于其他一些语营中存在的函 数指针"概念。与函数指针不同,委托是面向对象且类型安全的。 c1ass、 struct rae和 delegate类型全部都支持泛型,因此可以使用其他类型对它们进行参数化。 C#支持任意类型的一维和多维数组。与上述类型不同,数组类型无需先声明即可使用。相反,数组类型是通过 在类型名称后面添加方括号构造而成。例如,nt是int类型的一维数组,int1是nt类型的二维数 组,int是由int类型的一维数组或交错数组构成的一维数组 可以为nu的类型不需要单独定义。对于所有不可以为nu的类型T,都有对应的可以为nu的类型T?,后 者可以包含附加值mu1l例如,1nt?是可保存任何32位整数或mul值的类型, string?是可以保存任何 string或nu1值的类型。 C#采用统一的类型系统,因此任意类型的值都可视为 object。每种C#类型都直接或间接地派生自 object类 类型,而 object是所有类型的最终基类。只需将值视为类型 object,即可将引用类型的值视为对象。通过执 行装箱和取消装箱操作可以将值类型的值视为对象。在以下示例中,int值被转换成 object,然后又恢复 bject o= i; // Boxing int j =(int)o; / Unboxing 将值类型的值分配给 object对象引用时,会分配一个箱来保存此值。该箱是引用类型的实例,此值会被复制 到该箱。相反,当 object引用被显式转换成值类型时,将检查引用的 object是否是具有正确值类型的箱。如 果检查成功,则会捋箱中的值复制到值类型。 C#的统一类型系统实际上意味着按需":值类型视为 object引用。鉴于这种统一性,使用类型oet的常
int i = 123; object o = i; // Boxing int j = (int)o; // Unboxing 引用类型 元组值类型 值为 null 的其他所有值类型的扩展 格式为 (T1, T2, ...) 的用户定义类型 类类型 接口类型 数组类型 委托类型 其他所有类型的最终基类: object Unicode 字符串: string ,表示 UTF-16 代码单元序列 格式为 class C {...} 的用户定义类型 格式为 interface I {...} 的用户定义类型 一维、多维和交错。 例如: int[] 、 int[,] 和 int[][] 格式为 delegate int D(...) 的用户定义类型 C# 程序使用 类型声明 创建新类型。 类型声明指定新类型的名称和成员。 用户可定义以下六种 C# 类型:类类 型、结构类型、接口类型、枚举类型、委托类型和元组值类型。 class 类型定义包含数据成员(字段)和函数成员(方法、属性及其他)的数据结构。 类类型支持单一继承和多 形性,即派生类可以扩展和专门针对基类的机制。 struct 类型定义包含数据成员和函数成员的结构,这一点与类类型相似。 不过,与类不同的是,结构是值类 型,通常不需要进行堆分配。 结构类型不支持用户指定的继承,并且所有结构类型均隐式继承自类型 object 。 interface 类型将协定定义为一组已命名的公共成员。 实现 interface 的 class 或 struct 必须提供接口 成员的实现代码。 interface 可以继承自多个基接口, class 和 struct 可以实现多个接口。 delegate 类型表示引用包含特定参数列表和返回类型的方法。 通过委托,可以将方法视为可分配给变量并 可作为参数传递的实体。 委托类同于函数式语言提供的函数类型。 它们还类似于其他一些语言中存在的“函 数指针”概念。 与函数指针不同,委托是面向对象且类型安全的。 class 、 struct 、 interface 和 delegate 类型全部都支持泛型,因此可以使用其他类型对它们进行参数化。 C# 支持任意类型的一维和多维数组。 与上述类型不同,数组类型无需先声明即可使用。 相反,数组类型是通过 在类型名称后面添加方括号构造而成。 例如, int[] 是 int 类型的一维数组, int[,] 是 int 类型的二维数 组, int[][] 是由 int 类型的一维数组或“交错”数组构成的一维数组。 可以为 null 的类型不需要单独定义。 对于所有不可以为 null 的类型 T ,都有对应的可以为 null 的类型 T? ,后 者可以包含附加值 null 。 例如, int? 是可保存任何 32 位整数或 null 值的类型, string? 是可以保存任何 string 或 null 值的类型。 C# 采用统一的类型系统,因此任意类型的值都可视为 object 。 每种 C# 类型都直接或间接地派生自 object 类 类型,而 object 是所有类型的最终基类。 只需将值视为类型 object ,即可将引用类型的值视为对象。 通过执 行 装箱 和 取消装箱操作,可以将值类型的值视为对象。 在以下示例中, int 值被转换成 object ,然后又恢复 成 int 。 将值类型的值分配给 object 对象引用时,会分配一个“箱”来保存此值。 该箱是引用类型的实例,此值会被复制 到该箱。 相反,当 object 引用被显式转换成值类型时,将检查引用的 object 是否是具有正确值类型的箱。 如 果检查成功,则会将箱中的值复制到值类型。 C# 的统一类型系统实际上意味着“按需”将值类型视为 object 引用。 鉴于这种统一性,使用类型 object 的常
规用途库可以与派生自 object的所有类型结合使用,包括引用类型和值类型 C#有多种变量,其中包括字段、数组元素、局部变量和参数。变量表示存储位置。每个变量都具有一种类型,用 于确定可以在变量中存储哪些值,如下文所述 不可以为null的值类型 具有精确类型的值 可以为nu的值类型 omun值或具有精确类型的值 object omu引用、对任意引用类型的对象的引用,或对任意值类型的装箱值的引用 类类型 u1l引用、对类类型实例的引用或对派生自类类型的类实例的引用 接口类型 ml引用、对实现接口类型的类类型实例的引用或对实现接口类型的值类型的装箱值的引用 数组类型 onu1引用、对数组类型实例的引用,或对兼容的数组类型实例的引用 委托类型 nu11引用或对兼容的委托类型实例的引用 程序结构 C#中的关键组织结构概念包括程序、命名空间、类型、成员和程序集*。程序声明类型,而类型则包含成员,并 被整理到命名空间中。类型示例包括类、结构和接口。成员示例包括字段、方法、属性和事件。编译完的C#程 序实际上会打包到程序集中。程序集的文件扩展名通常为exe或,d11,具体视其分别实现的是应用程序还是 库_**而定 作为一个小示例,请考虑包含以下代码的程序集
程序结构 规用途库可以与派生自 object 的所有类型结合使用,包括引用类型和值类型。 C# 有多种 变量,其中包括字段、数组元素、局部变量和参数。 变量表示存储位置。 每个变量都具有一种类型,用 于确定可以在变量中存储哪些值,如下文所述。 不可以为 null 的值类型 可以为 null 的值类型 object 类类型 接口类型 数组类型 委托类型 具有精确类型的值 null 值或具有精确类型的值 null 引用、对任意引用类型的对象的引用,或对任意值类型的装箱值的引用 null 引用、对类类型实例的引用,或对派生自类类型的类实例的引用 null 引用、对实现接口类型的类类型实例的引用,或对实现接口类型的值类型的装箱值的引用 null 引用、对数组类型实例的引用,或对兼容的数组类型实例的引用 null 引用或对兼容的委托类型实例的引用 C# 中的关键组织结构概念包括程序、命名空间、类型、成员和程序集* 。 程序声明类型,而类型则包含成员,并 被整理到命名空间中。 类型示例包括类、结构和接口。 成员示例包括字段、方法、属性和事件。 编译完的 C# 程 序实际上会打包到程序集中。 程序集的文件扩展名通常为 .exe 或 .dll ,具体视其分别实现的是应用程序还是 库_***而定。 作为一个小示例,请考虑包含以下代码的程序集:
namespace Acme. Collections public class Stack<T Entrytop; public void Push(T data) p ne public T Pop() throw new InvalidoperationException() T result =top. Data return result class Entry public Entry Next i get; set; I public T Datai get; set; public Entry(Entry next, T data) Next next 此类的完全限定的名称为 Acme Collections. Stack。此类包含多个成员:一个top字段、两个方法(push和 Pp)和一个Etry嵌套类。 Entry类还包含三个成员:一个neot字段、一个dta字段和一个构造函数。 Stack是泛型类。它具有一个类型参数T,在使用时替换为具体类型。 NOTE 堆栈是一个"先进后出"(Fo)集合。添加到堆栈顶部的新元素。删除元素时,捋从堆栈顶部删除该元秦 程序集包含中间语营(L)指合形式的可执行代码和元数据形式的符号信息。执行前,NET公共语营运行时的实 时(m编译器会捋程序集中的代码转换为特定于处理器的代码。 由于程序集是包含代码和元数据的自描述功能单元,因此无需在C#中使用# include指合和头文件。只需在编 译程序时引用特定的程序集,即可在C#程序中使用此程序集中包含的公共类型和成员。例如,此程序使用 acme. dI1程序集中的 Acme. Collections. Stack类
using System; namespace Acme.Collections { public class Stack<T> { Entry _top; public void Push(T data) { _top = new Entry(_top, data); } public T Pop() { if (_top == null) { throw new InvalidOperationException(); } T result = _top.Data; _top = _top.Next; return result; } class Entry { public Entry Next { get; set; } public T Data { get; set; } public Entry(Entry next, T data) { Next = next; Data = data; } } } } NOTE 此类的完全限定的名称为 Acme.Collections.Stack 。 此类包含多个成员:一个 top 字段、两个方法( Push 和 Pop )和一个 Entry 嵌套类。 Entry 类还包含三个成员:一个 next 字段、一个 data 字段和一个构造函数。 Stack 是泛型类。 它具有一个类型参数 T ,在使用时替换为具体类型。 堆栈是一个“先进后出”(FILO) 集合。 添加到堆栈顶部的新元素。 删除元素时,将从堆栈顶部删除该元素。 程序集包含中间语言 (IL) 指令形式的可执行代码和元数据形式的符号信息。 执行前,.NET 公共语言运行时的实 时 (JIT) 编译器会将程序集中的 IL 代码转换为特定于处理器的代码。 由于程序集是包含代码和元数据的自描述功能单元,因此无需在 C# 中使用 #include 指令和头文件。 只需在编 译程序时引用特定的程序集,即可在 C# 程序中使用此程序集中包含的公共类型和成员。 例如,此程序使用 acme.dll 程序集中的 Acme.Collections.Stack 类: