c# 10 教程:5 .NET 概述

.NET 6 运行时的几乎所有功能都是通过大量托管类型公开的。这些类型组织到分层命名空间中,并打包到一组程序集中。

某些 .NET 类型由 CLR 直接使用,对于托管宿主环境至关重要。这些类型驻留在名为 的程序集中.dll包括 C# 的内置类型以及基本集合类,以及用于流处理、序列化、反射、线程处理和本机互操作性的类型。

注意

.dll取代了.NET Framework的。官方文档中的许多地方仍然提到mscorlib。

在此级别之上是“充实”CLR 级别功能的其他类型,提供 XML、JSON、网络和语言集成查询等功能。它们构成了基类库 (BCL)。位于此之上的是应用程序,它们提供用于开发特定类型的应用程序(如 Web 或富客户端)的 API。

在本章中,我们提供以下内容:

  • BCL的概述(我们将在本书的其余部分介绍)
  • 应用程序层的高级摘要

.NET 6 中的新增功能

在 .NET 6 中,基类库具有许多新功能。特别:

  • 新的 DateOnly / TimeOnly 结构清晰地捕获日期或时间,用于记录生日或闹钟时间等场景的日期或时间(请参阅中的“DateOnly 和 TimeOnly”)。
  • 新的 BitOperations 静态类提供对低级 base-2 数字运算的访问(请参阅中的)。
  • 添加了以下新的 LINQ 方法:Chunk、DistinctBy 、UnionBy 、IntersectBy 、ExceptBy 、MinBy 和 MaxBy(参见)。Take 现在也接受 Range 变量。
  • 新的 JsonNode API 提供了一个流畅的可写 DOM,其类型不需要处置(参见中的)。Utf8JsonWriter现在也有一个WriteRawValue方法。
  • 新的 RandomAccess 类提供高性能的线程安全文件 I/O 操作。
  • System.Reflection中新的NullabilityInfoContext类查询可空性注释(参见中的“NullabilityContextInfo”)。
  • System.Security.Cryptography 中的 RandomNumberGenerator 类现在有一个静态的 GetBytes(int) 方法,该方法在一个操作中返回一个随机字节数组。还有一些新的方法来简化加密和解密(参见中的)。
  • 并行类上的新 ForEachAsync 方法限制了异步并发性(参见中的)。任务现在还有一个 WaitAsync 方法,该方法将超时应用于任何异步操作,并且有一个新的计时器设计用于使用 await(参见中的)。
  • 新的 NativeMemory 类围绕低级内存分配操作(如 malloc)提供了一个轻量级包装器。

.NET 6 还对运行时进行了大量性能改进,并增强了对 Windows ARM64 和 Apple M1/M2 处理器的支持。

在应用层,最大的变化是引入了 MAUI(多平台应用 UI,2022 年初),它取代了 Xamarin 进行跨平台移动开发。MAUI 还支持 macOS 和 Windows 的跨平台桌面应用程序开发,并面向统一的 .NET 6 CLR/BCL。UWP还有一个继任者,Windows App SDK(以WinUI 3作为其表示层),并且出现了一种称为Blazor Desktop的新技术,用于编写基于HTML的桌面和移动应用程序。

.NET 标准

如果 NuGet 上提供的大量公共库仅支持 .NET 6,则它们的价值就不那么高了。编写库时,通常需要支持各种平台和运行时版本。若要在不为每个运行时创建单独的生成的情况下实现该目标,必须以最低公分母为目标。如果您只希望支持 .NET 6 的直接前身,这相对容易:例如,如果您面向 .NET Core 3.0,您的库将在 .NET Core 3.0、.NET Core 3.1 和 .NET 5+ 上运行。

如果您还想支持.NET Framework或Xamarin,情况会变得更加混乱。这是因为这些运行时中的每一个都有一个具有重叠功能的 CLR 和 BCL — 没有一个运行时是其他运行时的纯子集。

通过定义跨整个旧运行时范围的人工子集来解决此问题。通过面向 .NET Standard,您可以轻松编写具有广泛影响力的库。

注意

.NET 标准不是运行时;它只是一个描述功能(类型和成员)的最小基线的规范,以保证与一组特定的运行时兼容。该概念类似于 C# 接口:.NET Standard 类似于具体类型(运行时)可以实现的接口。

.NET 标准 2.0

最有用的版本是。面向 .NET Standard 2.0 而不是特定运行时的库将在目前仍在使用的大多数新式和旧版运行时上运行,而无需修改,包括:

  • .NET Core 2.0+(包括 .NET 5 和 .NET 6)
  • UWP 10.0.16299+
  • Mono 5.4+(旧版本的 Xamarin 使用的 CLR/BCL)
  • .NET Framework 4.6.1+

若要面向 .NET 标准 2.0,请将以下内容添加到 文件中:

  <PropertyGroup>     <TargetFramework>netstandard2.0</TargetFramework>   <PropertyGroup>

本书中描述的大多数 API 都受 .NET Standard 2.0 支持。

.NET 标准 2.1

NET Standard 2.1 是 .NET Standard 2.0 的超集,它(仅)支持以下平台:

  • .NET Core 3+
  • 单声道 6.4+

任何版本的.NET Framework(甚至UWP都不支持.NET Standard 2.1),因此它比.NET Standard 2.0有用得多。

特别是以下 API 在 .NET Standard 2.1(但不是 .NET Standard 2.0)中可用:

  • 跨度<T>()
  • 反射.发射()
  • ValueTask<T>()

较旧的 .NET 标准

还有较旧的.NET标准,最值得注意的是1.1,1.2,1.3和1.6。编号较高的标准始终是编号较低的标准的严格超集。例如,如果您编写一个面向 .NET Standard 1.6 的库,则不仅支持最新版本的主要运行时,还支持 .NET Core 1.0。如果您的目标是 .NET Standard 1.3,则支持我们已经提到的所有内容以及 .NET Framework 4.6.0。下表详细说明了。

如果您定位...

你也支持...

标准 1.6

.NET Core 1.0

标准 1.3

以上加上 .NET 4.6.0

标准 1.2

以上加上.NET 4.5.1,Windows Phone 8.1,WinRT for Windows 8.1

标准 1.1

以上加上.NET 4.5.0,Windows Phone 8.0,WinRT for Windows 8.0

警告

1.x标准缺少2.0中存在的数千个API,包括我们在本书中描述的大部分内容。这可能会使面向 1.x 标准更具挑战性,尤其是在需要集成现有代码或库时。

您还可以将 .NET Standard 视为最低公分母。对于 .NET Standard 2.0,实现它的运行时具有类似的 BCL,因此最低公分母很大且有用。但是,如果您还希望与 .NET Core 1.0(BCL 大幅减少)兼容,则最低公分母 .NET Standard 1.x 将变得更小且不太有用。

.NET Framework 和 .NET 6 兼容性

由于 .NET Framework 已经存在了很长时间,因此遇到 .NET Framework 的库(没有 .NET Standard、.NET Core 或 .NET 6 等效项)的情况并不少见。为了帮助缓解这种情况,允许 .NET 5+ 和 .NET Core 项目引用 .NET Framework 程序集,但附带条件如下:

  • 如果 .NET Framework 程序集调用不受支持的 API,则会引发异常。
  • 重要的依赖项可能(并且经常)无法解析。

实际上,它最有可能在简单情况下工作,例如包装非托管 DLL 的程序集。

运行时和 C# 语言版本

默认情况下,项目的运行时版本确定使用的 C# 语言版本:

  • 对于 .NET 6,它是 。
  • 对于 .NET 5,它是 。
  • 对于.NET Core 3.x,Xamarin和.NET Standard 2.1,它是。
  • 对于 .NET Core 2.x、.NET Framework 和 .NET Standard 2.0 及更低版本,它是 。

这是因为更高版本的 C# 依赖于仅在更高运行时中可用的类型。

您可以使用 <LangVersion> 元素覆盖项目文件中的语言版本。将较旧的运行时(如 .NET 5)与较新的语言版本(如 C# 10)一起使用意味着依赖于较新的 .NET 类型的语言功能将不起作用(尽管在某些情况下,你可以自己定义这些类型)。

引用程序集

以 .NET Standard 为目标时,项目会隐式引用名为 的程序集,该程序集包含所选版本的 .NET Standard 允许的所有类型和成员。这称为,因为它的存在只是为了编译器的利益,并且不包含已编译的代码。在运行时,“真正的”程序集通过程序集重定向属性进行标识(程序集的选择将取决于程序集最终在哪个运行时和平台上运行)。

有趣的是,当您面向 .NET 6 时,也会发生类似的事情。项目隐式引用一组引用程序集,这些程序集的类型反映所选 .NET 版本的运行时程序集中的内容。这有助于实现版本控制和跨平台兼容性,还允许你将目标定位为与计算机上安装的版本不同的 .NET 版本。

CLR 和 BCL

系统类型

最基本的类型直接位于 System 命名空间中。其中包括 C# 的内置类型、异常基类、枚举、数组和委托基类,以及可为空、类型、日期时间、时间跨度和 Guid。系统命名空间还包括用于执行数学函数(数学)、生成随机数(随机)以及在各种类型之间转换(转换和位转换器)的类型。

介绍了这些类型以及定义跨.NET用于格式化(IFormattable)和顺序比较(IComparable)等任务的标准协议的接口。

System 命名空间还定义了用于与垃圾回收器交互的 IDisposable 接口和 GC 类,我们将在第 中介绍。

文本处理

命名空间包含 StringBuilder 类(字符串的可编辑或表亲)和用于处理文本编码的类型,如 UTF-8(编码及其子类型)。我们将在第中介绍这一点。

命名空间包含执行基于模式的高级搜索和替换操作的类型;我们将在第中描述这些。

收集

.NET 提供了各种用于管理项集合的类。其中包括基于列表和字典的结构;它们与一组统一其共同特征的标准接口协同工作。所有集合类型都在以下命名空间中定义,如所述:

System.Collections                 // Nongeneric collections System.Collections.Generic         // Generic collections System.Collections.Specialized     // Strongly typed collections System.Collections.ObjectModel     // Bases for your own collections System.Collections.Concurrent      // Thread-safe collection (Chapter 22)

查询

语言集成查询 (LINQ) 允许您对本地和远程集合(例如 SQL Server 表)执行类型安全查询,如第 章到 章所述。LINQ 的一大优点是,它跨各种域提供一致的查询 API。基本类型驻留在以下命名空间中:

System.Linq                  // LINQ to Objects and PLINQ System.Linq.Expressions      // For building expressions manually System.Xml.Linq              // LINQ to XML

XML 和 JSON

XML和JSON在.NET中得到广泛支持。完全关注 LINQ to XML,这是一种可以通过 LINQ 构造和查询的轻量级 XML 文档对象模型 (DOM)。介绍了高性能的低级XML读取器/编写器类,XML模式和样式表,以及使用JSON的类型:

System.Xml                // XmlReader, XmlWriter System.Xml.Linq           // The LINQ to XML DOM System.Xml.Schema         // Support for XSD System.Xml.Serialization  // Declarative XML serialization for .NET types System.Xml.XPath          // XPath query language System.Xml.Xsl            // Stylesheet support  System.Text.Json          // JSON reader/writer and DOM

在 的在线补充中,我们将介绍 JSON 序列化程序。

诊断

在第 中,我们将介绍日志记录和断言,并描述如何与其他进程交互、写入 Windows 事件日志以及处理性能监视。此类型在“系统诊断”中和“系统诊断”下定义。

并发和异步

许多现代应用程序需要同时处理多件事情。从 C# 5.0 开始,通过异步函数和高级构造(如任务和任务组合器)这变得更加容易。在从多线程的基础知识开始之后详细解释了所有这些。用于处理线程和异步操作的类型位于 System.Threading 和 System.Threading.Tasks 命名空间中。

流和输入/输出

.NET 为低级别输入/输出 (I/O) 提供基于流的模型。流通常用于直接读取和写入文件和网络连接,并且可以链接或包装在装饰器流中以添加压缩或加密功能。描述了流体系结构以及对处理文件和目录、压缩、管道和内存映射文件的特定支持。流和 I/O 类型在 System.IO 命名空间中和之下定义,文件 I/O 的 Windows 运行时 (WinRT) 类型位于 Windows.Storage 中和下。

联网

您可以通过 System.Net 中的类型直接访问大多数标准网络协议,例如 HTTP、TCP/IP 和 SMTP。在第 中,我们将演示如何使用这些协议中的每一种进行通信,从简单的任务开始,例如从网页下载,最后直接使用 TCP/IP 检索 POP3 电子邮件。以下是我们介绍的命名空间:

System.Net System.Net.Http          // HttpClient System.Net.Mail          // For sending mail via SMTP System.Net.Sockets       // TCP, UDP, and IP

程序集、反射和属性

C# 程序编译到的程序集包括可执行指令(存储为 IL)和元数据,后者描述程序的类型、成员和属性。通过反射,可以在运行时检查此元数据,并执行动态调用方法等操作。使用 Reflection.Emit ,您可以动态构建新代码。

在第中,我们描述了程序集的构成以及如何动态加载和隔离它们。在第 中,我们将介绍反射和属性 — 描述如何检查元数据、动态调用函数、编写自定义属性、发出新类型以及解析原始 IL。用于使用反射和使用程序集的类型驻留在以下命名空间中:

System System.Reflection System.Reflection.Emit

动态规划

在第中,我们将介绍动态编程和利用动态语言运行时(DLR)的一些模式。我们描述了如何实现模式,编写自定义动态对象以及与IronPython进行互操作。动态规划的类型位于 System.Dynamic 中。

密码学

.NET 为流行的哈希和加密协议提供了广泛的支持。在第 中,我们将介绍哈希、对称和公钥加密以及 Windows 数据保护 API。此类型在以下位置定义:

System.Security System.Security.Cryptography

高级线程

C# 的异步函数使并发编程变得更加容易,因为它们减少了对较低级别技术的需求。但是,有时仍然需要信令构造、线程本地存储、读取器/写入器锁定等。对此进行了深入的解释。线程类型位于 System.Threading 命名空间中。

并行编程

在第 中,我们将详细介绍利用多核处理器的库和类型,包括用于任务并行性、命令式数据并行性和功能并行性 (PLINQ) 的 API。

跨度<T>和内存<T>

为了帮助微优化性能热点,CLR 提供了多种类型来帮助您以减少内存管理器负载的方式进行编程。其中两种关键类型是 Span<T> 和 Memory<T> ,我们将在第 中描述。

本机和 COM 互操作性

可以与本机代码和组件对象模型 (COM) 代码进行互操作。本机互操作性允许您调用非托管 DLL 中的函数、寄存回调、映射数据结构以及与本机数据类型进行互操作。COM 互操作性允许您调用 COM 类型(在 Windows 计算机上),并向 COM 公开 .NET 类型。支持这些功能的类型在 System.Runtime.InteropServices 中,我们将在第 中介绍它们。

正则表达式

在第 中,我们将介绍如何使用正则表达式来匹配字符串中的字符模式。

序列化

.NET 提供了多个系统,用于将对象保存和还原为二进制或文本表示形式。此类系统可用于通信以及将对象保存和还原到文件中。在 的联机补充中,我们介绍了所有四个序列化引擎:二进制序列化程序、(新更新的)JSON 序列化程序、XML 序列化程序和数据协定序列化程序。

罗斯林编译器

C# 编译器本身是用 C# 编写的,该项目称为“Roslyn”,库以 NuGet 包的形式提供。使用这些库,除了将源代码编译到程序集之外,还可以以多种方式利用编译器的功能,例如编写代码分析和重构工具。我们在 的在线增刊中介绍了罗斯林。

应用层

基于用户界面 (UI) 的应用程序可分为两类:客户端(相当于网站)和(最终用户必须在计算机或移动设备上下载并安装的程序)。

对于用C#编写瘦客户端应用程序,有 ASP.NET Core,它可以在Windows,Linux和macOS上运行。ASP.NET Core也是为编写Web API而设计的。

对于富客户端应用程序,可以选择 API:

  • Windows 桌面层包括 WPF 和 Windows Forms API,并在 Windows 7/8/10/11 桌面上运行。
  • UWP 允许你编写在 Windows 10+ 桌面和设备上运行的 Windows 应用商店应用。
  • WinUI 3(Windows App SDK)是UWP的最新继任者,可在Windows 10 +桌面上运行。
  • MAUI(以前称为 Xamarin)在 iOS 和 Android 移动设备上运行。MAUI 还允许面向 macOS 和 Windows 的跨平台桌面应用程序。

还有第三方库,例如Avalonia,它提供跨平台的UI支持。

ASP.NET 核心

ASP.NET Core 是 ASP.NET 的轻量级模块化继承者,适用于创建网站、基于 REST 的 Web API 和微服务。它还可以与两个流行的单页应用程序框架一起运行:React和Angular。

ASP.NET 支持流行的 (MVC) 模式,以及称为 Blazor 的新技术,其中客户端代码是用 C# 而不是 JavaScript 编写的。

ASP.NET Core 在 Windows、Linux 和 macOS 上运行,并且可以在自定义进程中自托管。与其前身.NET Framework(ASP.NET)不同,ASP.NET Core不依赖于System.Web和Web表单的历史包袱。

与任何瘦客户端体系结构一样,ASP.NET Core 与富客户端相比具有以下一般优势:

  • 客户端的部署为零。
  • 客户端可以在支持 Web 浏览器的任何平台上运行。
  • 更新易于部署。

视窗桌面

Windows 桌面应用程序层提供了两种用于编写胖客户端应用程序的 UI API 选择:WPF 和 Windows 窗体。这两个 API 都在 Windows Desktop/Server 7 到 11 上运行。

可湿性工作基金会

WPF 于 2006 年推出,此后得到了增强。与其前身 Windows 窗体不同,WPF 使用 DirectX 显式呈现控件,具有以下优点:

  • 它支持复杂的图形,例如任意转换、3D 渲染、多媒体和真正的透明度。通过样式和模板支持外观。
  • 其主要测量单位不是基于像素的,因此应用程序在任何 DPI 设置下都能正确显示。
  • 它具有广泛而灵活的布局支持,这意味着您可以本地化应用程序而不会有元素重叠的危险。
  • 它使用 DirectX 可以加快渲染速度,并能够利用图形硬件加速。
  • 它提供可靠的数据绑定。
  • 可以在 XAML 文件中以声明方式描述 UI,这些文件可以独立于“代码隐藏”文件进行维护,这有助于将外观与功能分开。

WPF 由于其大小和复杂性,需要一些时间来学习。用于编写 WPF 应用程序的类型位于 System.Windows 命名空间和除 System.Windows.Forms 之外的所有子命名空间中。

窗口窗体

Windows 窗体是一个富客户端 API,在 2000 年随 .NET Framework 的第一个版本一起提供。与 WPF 相比,Windows 窗体是一种相对简单的技术,它提供了编写典型 Windows 应用程序所需的大多数功能。它在维护旧版应用程序方面也具有重要意义。但与 WPF 相比,它有许多缺点,其中大部分源于它是 GDI+ 和 Win32 控件库的包装器:

  • 尽管它提供了 DPI 感知机制,但编写在 DPI 设置与开发人员不同的客户端上中断的应用程序仍然太容易了。
  • 用于绘制非标准控件的 API 是 GDI+,尽管它相当灵活,但在呈现大区域时速度很慢(如果没有双重缓冲,可能会闪烁)。
  • 控制缺乏真正的透明度。
  • 大多数控件是非组合的。例如,不能将图像控件放在选项卡控件标头中。在 Windows 窗体中,以使用 WPF 时微不足道的方式自定义列表视图、组合框和选项卡控件既耗时又痛苦。
  • 动态布局很难可靠地正确实现。

最后一点是偏爱 WPF 而不是 Windows 窗体的一个很好的理由,即使您编写的业务应用程序只需要 UI 而不是“用户体验”。WPF 中的布局元素(如 Grid)使组合标签和文本框变得容易,以便它们始终对齐(即使在语言更改本地化之后),而不会产生混乱的逻辑和闪烁。此外,您不需要屈服于屏幕分辨率的最低公分母 - WPF 布局元素从一开始就设计为能够正确适应调整大小。

从积极的方面来看,Windows 窗体相对容易学习,并且仍然具有大量的第三方控件。

Windows 窗体类型位于 System.Windows.Forms(在 .dll 中)和 System.Drawing(在 中)命名空间中。后者还包含用于绘制自定义控件的 GDI+ 类型。

UWP 和 WinUI 3

UWP 是一个富客户端 API,用于编写面向 Windows 10+ 桌面和设备的触摸优先 UI。“通用”一词是指它在一系列Windows 10设备上运行的能力,包括Xbox,Surface Hub和HoloLens。但是,它与早期版本的Windows不兼容,包括Windows 7和Windows 8 / 8.1。

UWP API 使用 XAML,有点类似于 WPF。以下是它的主要区别:

  • UWP 应用的主要分发模式是 Windows 应用商店。
  • UWP 应用在沙盒中运行以减少恶意软件的威胁,这意味着它们无法执行读取或写入任意文件等任务,并且无法使用管理提升运行。
  • UWP 依赖于属于操作系统 (Windows) 的 WinRT 类型,而不是托管运行时。这意味着在编写应用时,必须指定 Windows 版本范围(例如 Windows 10 内部版本 17763 到 Windows 10 内部 18362)。这意味着你要么需要以旧 API 为目标,要么要求你的客户安装最新的 Windows 更新。

由于这些差异造成的限制,UWP 从未成功地匹配 WPF 和 Windows 窗体的流行程度。为了解决这个问题,Microsoft引入了一项新技术来取代UWP,称为Windows App SDK(具有一个名为WinUI 3的UI层)。

Windows 应用 SDK 将 WinRT API 从操作系统传输到运行时,从而公开完全托管的界面,并且无需以特定操作系统版本范围为目标。它还:

  • 更好地与 Windows 桌面 API(Windows 窗体和 WPF)集成
  • 允许您编写在 Windows 应用商店沙盒之外运行的应用程序
  • 在最新的 .NET 上运行(而不是像 UWP 那样绑定到 .NET Core 2.2)

但是,在撰写本文时,Windows App SDK不支持Xbox或HoloLens。

MAUI

MAUI(2022 年初)是 Xamarin 的新化身,可让您使用 C# 开发面向 iOS 和 Android 的移动应用程序(以及面向 macOS 和 Windows 的跨平台桌面应用程序)。

在iOS和Android上运行的CLR / BCL称为Mono(开源Mono运行时的派生版本)。从历史上看,Mono 并不完全兼容 .NET,在 Mono 和 .NET 上运行的库将面向 .NET Standard。在MAUI中,Mono的公共接口与.NET 6合并,使Mono实际上成为.NET 6的。

MAUI 新增功能包括统一的项目界面、热重载、对 Blazor 桌面和混合应用的支持,以及改进的性能和启动时间。有关详细信息,请参阅 。

版权声明:

作者: freeclashnode

链接: https://www.freeclashnode.com/news/article-3547.htm

来源: FreeClashNode

文章版权归作者所有,未经允许请勿转载。

免费节点实时更新

热门文章

最新文章

归档