[C#] C#深入浅出4th Edition [2]

1.1.5 平衡效率和复杂性

  我记得我第一次使用 Java 的经历; 它被完全解释并且非常缓慢。 一段时间后,可选的即时 (JIT) 编译器变得可用,最终几乎理所当然地认为任何 Java 实现都是 JIT 编译的。

  使 Java 表现良好需要付出很多努力。 如果语言失败了,这种努力就不会发生。 但开发人员看到了潜力,并且已经感觉比以前更有效率。 开发和交付速度通常比应用程序速度更重要。

  C# 的情况略有不同。 公共语言运行时 (CLR) 从一开始就非常高效。 对与本机代码的轻松互操作以及对性能敏感的带指针的不安全代码的语言支持也有帮助。 随着时间的推移,C# 性能不断提高。 (我苦笑着注意到微软现在正在引入分层 JIT 编译,就像 Java HotSpot JIT 编译器一样。)

  但是不同的工作负载有不同的性能需求。 正如您将在第 1.2 节中看到的那样,C# 现在在各种各样的平台上得到使用,包括游戏和微服务,这两个平台都可能有困难的性能要求。

  在某些情况下,异步有助于解决性能问题,但 C# 7 是对性能最为敏感的版本。 只读结构和更大的 ref 功能表面积有助于避免冗余复制。 现代框架中存在并由类似 ref 的结构类型支持的 Span 功能减少了不必要的分配和垃圾收集。 希望很明显,当谨慎使用时,这些技术将迎合特定开发人员的要求。

  我对这些功能有一点不安,因为它们对我来说仍然很复杂。 我无法像常规值参数一样清楚地推断使用 in 参数的方法,而且我敢肯定,我需要一段时间才能对 ref locals 能做什么和不能做什么感到满意和 参考返回。

  我希望这些功能将被适度使用。 他们将在受益的情况下简化代码,毫无疑问,他们会受到维护该代码的开发人员的欢迎。 我期待在个人项目中试验这些功能,并在提高性能和增加代码复杂性之间取得平衡。

  我不想大声地发出这个警告。 我怀疑 C# 团队做出了正确的选择来包含新功能,无论我在工作中使用多少或很少使用它们。 我只是想指出,您不必仅仅因为它就在那里就使用它。 做出选择复杂性的决定是有意识的。 说到选择加入,C# 7 带来了一个新的元特性:自 C# 1 以来首次使用次要版本号。

1.1.6 快速进化:使用次要(minor)版本

  C# 的版本号集很奇怪,而且由于许多开发人员在框架和语言之间存在可以理解的混淆,这使情况变得复杂。 (例如,没有 C# 3.5。.NET Framework 3.0 版与 C# 2 一起发布,.NET 3.5 与 C# 3 一起发布。)C# 1 有两个版本:C# 1.0 和 C# 1.2。 在 C# 2 和 C# 6(包括 C# 2 和 C# 6)之间,只有主要版本通常由新版本的 Visual Studio 支持。

  C# 7 逆势而上:发布了 C# 7.0、C# 7.1、C# 7.2 和 C# 7.3,它们都在 Visual Studio 2017 中可用。我认为这种模式很可能会在 C# 8 中继续存在。目标 是允许新功能随着用户反馈快速发展。 C# 7.1–7.3 的大部分特性都是对 C# 7.0 中引入的特性的调整或扩展。

  语言特征的波动性可能令人不安,尤其是在大型组织中。 许多基础设施可能需要更改或升级,以确保完全支持新的语言版本。 许多开发人员可能会以不同的速度学习和采用新功能。 如果不出意外,语言变化比你习惯的更频繁可能会有点不舒服。

  因此,C# 编译器默认使用其支持的最新主要版本的最早次要版本。 如果您使用 C# 7 编译器并且未指定任何语言版本,则默认情况下会将您限制为 C# 7.0。 如果您想使用更高的次要版本,您需要在项目文件中指定它并选择使用新功能。 您可以通过两种方式执行此操作,尽管它们具有相同的效果。 您可以直接编辑项目文件以在 < PropertyGroup > 中添加 < LangVersion > 元素,如下所示:


	 ... 
	 latest 

[C#] C#深入浅出4th Edition [2]_第1张图片
图 1.1 Visual Studio 中的语言版本设置

  如果您不喜欢直接编辑项目文件,可以在 Visual Studio 中转到项目属性,选择“构建”选项卡,然后单击右下角的“高级”按钮。 高级构建设置对话框,如图 1.1 所示,将打开以允许您选择要使用的语言版本和其他选项。

  对话框中的这个选项不是新的,但与以前的版本相比,您现在更有可能使用它。 您可以选择的值如下:

  • default — 最新主要版本的第一个版本
  • latest — 最新版本
  • 特定版本号 —— 例如,7.0 或 7.3

  这不会改变你运行的编译器的版本; 它会更改您可用的语言功能集。 如果您尝试使用目标版本中不可用的东西,编译器错误消息通常会说明该功能需要哪个版本。 如果您尝试使用编译器完全不知道的语言功能(例如,使用带有 C# 6 编译器的 C# 7 功能),错误消息通常不太清楚。

  自首次发布以来,C# 作为一门语言已经走过了漫长的道路。 它运行的平台呢?

1.2 不断发展的平台

  过去几年对 .NET 开发人员来说是令人振奋的。 由于微软和 .NET 社区都接受了更开放的开发模型的含义,因此也存在一定程度的挫败感。 但是这么多人的辛勤工作的总体结果是显着的。

  多年来,运行 C# 代码几乎总是意味着在 Windows 上运行。 它通常意味着使用 Windows 窗体或 Windows Presentation Foundation (WPF) 编写的客户端应用程序,或者使用 ASP.NET 编写并可能在 Internet Information Server (IIS) 后面运行的服务器端应用程序。 其他选项早就有了,尤其是 Mono 项目有着悠久的历史,但 .NET 开发的主流仍然在 Windows 上。

  当我在 2018 年 6 月写这篇文章时,.NET 世界非常不同。 最突出的开发是 .NET Core,它是一个可移植和开源的运行时和框架,在多个操作系统上得到 Microsoft 的完全支持,并具有流线型开发工具。 就在几年前,这还是不可想象的。 再加上 Visual Studio Code 形式的可移植和开源 IDE,您将获得一个蓬勃发展的 .NET 生态系统,开发人员在各种本地平台上工作,然后部署到各种服务器平台。

  过分关注 .NET Core 而忽略了当今 C# 的许多其他运行方式是错误的。 Xamarin 提供了丰富的多平台移动体验。 它的 GUI 框架 (Xamarin Forms) 允许开发人员在适当的情况下创建跨不同设备相当统一的用户界面,但也可以利用底层平台。

  Unity 是世界上最受欢迎的游戏开发平台之一。 借助自定义的 Mono 运行时和提前编译,它可以为习惯于更传统运行时环境的 C# 开发人员带来挑战。 但是对于许多开发人员来说,这是他们第一次或者可能是唯一一次使用该语言的经验。

  这些被广泛采用的平台远不是唯一制作 C# 的平台。 我最近一直在使用 Try .NET 和 Blazor 进行非常不同形式的浏览器/C# 交互。

  Try .NET 允许用户在具有自动完成功能的浏览器中编写代码,然后构建并运行该代码。 它非常适合以尽可能低的准入门槛来试验 C#。

  Blazor 是一个直接在浏览器中运行 Razor 页面的平台。 这些不是由服务器渲染然后显示在浏览器中的页面; 用户界面代码使用转换为 Web 程序集的 Mono 运行时版本在浏览器中运行。 整个运行时通过浏览器中的 JavaScript 引擎执行中间语言 (IL) 的想法,不仅在完整的计算机上,而且在手机上,几年前让我觉得很荒谬。 我很高兴其他开发人员有更多的想象力。 只有通过比以往任何时候都更加协作和开放的社区,才能实现这一领域的许多创新。

1.3 不断发展的社区

  我从 C# 1.0 时代就开始参与 C# 社区,我从未见过它像今天这样充满活力。 当我开始使用 C# 时,它被视为一种“企业”编程语言,并没有多少乐趣和探索感。1 在这样的背景下,与包括 Java 在内的其他语言相比,开源 C# 生态系统的增长相当缓慢 ,这也被认为是一种企业语言。 大约在 C# 3 的时候,alt.NET 社区正在超越 .NET 开发的主流,这在某种意义上被视为与 Microsoft 的对立。

  2010 年,推出了 NuGet(最初是 NuPack)包管理器,这使得生产和使用类库变得更加容易,无论是商业的还是开源的。 尽管下载 zip 文件、将 DLL 复制到适当的地方,然后添加对它的引用的障碍听起来并不重要,但每一个摩擦点都会让开发人员望而却步。

注意 NuGet 以外的包管理器开发得更早,Sebastien Lambla 开发的 OpenWrap 项目尤其有影响力。

  快进到 2014 年,微软宣布其 Roslyn 编译器平台将在新的 .NET 基金会的保护下成为开源。 然后 .NET Core 以最初的代号 Project K 发布; DNX 出现较晚,随后是已发布且稳定的 .NET Core 工具。 然后是 ASP.NET Core。 和实体框架核心。 和 Visual Studio 代码。 在 GitHub 上真正生活和呼吸的产品列表还在继续。

  这项技术很重要,但微软对开源的新拥抱对于一个健康的社区同样重要。 第三方开源包蓬勃发展,包括对 Roslyn 的创新使用以及在 .NET Core 工具中的集成,感觉恰到好处。

  这一切都不是在真空中发生的。 云计算的兴起使 .NET Core 对 .NET 生态系统的重要性比其他情况下更加重要; 对 Linux 的支持不是可选的。 但是由于 .NET Core 可用,现在将 ASP.NET Core 服务打包到 Docker 映像中,使用 Kubernetes 部署它,并将其用作可能涉及许多人的大型应用程序的一部分,并没有什么特别之处。 语言。 许多社区之间的好想法的交叉授粉一直存在,但现在比以往任何时候都更强大。

  您可以在浏览器中学习 C#。 您可以在任何地方运行 C#。 您可以在 Stack Overflow 和无数其他网站上询问有关 C# 的问题。 您可以在 C# 团队的 GitHub 存储库中加入有关该语言未来的讨论。 这并不完美; 为了让 C# 社区尽可能地欢迎每个人,我们仍然有集体工作要做,但我们已经处于一个很好的位置。

我想 C# in Depth 在 C# 社区中也有自己的小地方。 这本书是如何演变的?

1.4 一本不断发展的书

  您正在深入阅读 C# 的第四版。 尽管这本书的发展速度与语言、平台或社区的发展速度不同,但它也发生了变化。 本节将帮助您了解本书所涵盖的内容。

1.4.1 混合级别覆盖

  第一版 C# in Depth 于 2008 年 4 月出版,巧合的是我加入 Google 的时间。 那时,我知道许多开发人员对 C# 1 相当了解,但他们在学习 C# 2 和 C# 3 时没有牢牢掌握所有部分是如何组合在一起的。 我的目标是通过深入研究语言来解决这个差距,这将帮助读者不仅了解每个功能的作用,而且了解为什么要这样设计。

  随着时间的推移,开发人员的需求会发生变化。 在我看来,社区几乎通过渗透吸收了对该语言的更深入理解,至少对于早期版本而言。 对语言进行更深入的理解不会是一种普遍的体验,但对于第四版,我希望重点放在较新的版本上。 我仍然认为逐个版本了解语言版本的演变是有用的,但无需查看 C# 2-4 中功能的每个细节。

注意 一次只看一个版本的语言并不是从头开始学习该语言的最佳方法,但如果您想深入理解它,它会很有用。 我不会使用相同的结构来为 C# 初学者写一本书

  我也不喜欢厚书。 我不希望 C# in Depth 令人生畏、难以掌握或难以书写。为 C# 2-4 保留 400 页的报道感觉不对。 出于这个原因,我压缩了这些版本的覆盖范围。 提到了每一个功能,我会在我认为合适的地方详细介绍,但深度不如第三版。 使用第四版中的报道作为对您已经知道的主题的回顾,并帮助您确定您想在第三版中阅读更多的主题。 您可以在 www.manning.com/books/c-sharp-in-depth-fourth-edition 找到访问第三版电子版的链接。 本版更详细地介绍了该语言的第 5-7 版。 异步仍然是一个难以理解的话题,第三版显然根本没有涵盖 C# 6 或 7。

  与软件工程一样,写作通常是一种平衡行为。 我希望我在细节和简洁之间取得的平衡对你有用。

提示 如果您有本书的实体副本,我强烈建议您在其中写下。 记下您不同意的地方或特别有用的部分。 这样做会强化你记忆中的内容,而这些笔记将在以后起到提醒作用。

1.4.2 使用 Noda 时间的例子

  我在书中提供的大多数示例都是独立的。 但要为某些功能提供更令人信服的案例,能够指出我在生产代码中使用它们的位置很有用。 大多数时候,我为此使用 Noda Time。

  Noda Time 是我在 2009 年开始的一个开源项目,旨在为 .NET 提供更好的日期和时间库。 不过,它还有一个次要目的:对我来说,它是一个很棒的沙盒项目。 它帮助我磨练我的 API 设计技能,了解有关性能和基准测试的更多信息,并测试新的 C# 功能。 当然,所有这些都不会破坏用户。

  每个新版本的 C# 都引入了我在 Noda Time 中可以使用的特性,所以我认为在本书中使用这些作为具体示例是有意义的。 所有代码都可以在 GitHub 上找到,这意味着您可以克隆它并自己进行试验。 在示例中使用 Noda Time 的目的不是说服您使用该库,但如果这恰好是副作用,我不会抱怨。

  在本书的其余部分,当我提到 Noda Time 时,我假设你知道我在说什么。 在使其适用于示例方面,它的重要方面如下:

  • 代码需要尽可能可读。 如果一个语言特性让我重构可读性,我会抓住这个机会。

  • Noda Time 遵循语义版本控制,新的主要版本很少见。 我关注应用新语言特性的向后兼容性方面。

  • 我没有具体的性能目标,因为 Noda Time 可以在具有不同要求的许多环境中使用。 我确实关注性能,并且会采用提高效率的功能,只要它们不会使代码变得更加复杂。

要了解有关该项目的更多信息并查看其源代码,请访问 https://nodatime.org 或 https://github.com/nodatime/nodatime。

1.4.3 术语选择

  我试图在书中尽可能地遵循官方的 C# 术语,但有时我会允许清晰性优先于精确性。 例如,在撰写有关异步的文章时,我经常提到异步方法,而同样的信息也适用于异步匿名函数。 同样,对象初始值设定项适用于可访问字段和属性,但更简单的是提及一次,然后在其余说明中仅引用属性。

  有时,规范中的术语很少在更广泛的社区中使用。 例如,规范具有函数成员的概念。 这是一个方法、属性、事件、索引器、用户定义的运算符、实例构造函数、静态构造函数或终结器。 它是可以包含可执行代码的任何类型成员的术语,在描述语言特性时很有用。 当您查看自己的代码时,它几乎没有那么有用,这就是为什么您以前可能从未听说过它。 我试着谨慎地使用这样的术语,但我的观点是,本着更接近语言的精神,成为一些熟悉它们的人是值得的。

  最后,一些概念没有任何官方术语,但仍然可以以简写形式引用。 我最常使用的可能是难以描述的名称。这个术语由 Eric Lippert 创造,指的是由编译器生成的标识符,用于实现迭代器块或 lambda 表达式等功能。该标识符对 CLR 有效,但不适用于 在 C# 中有效; 这是一个无法在语言中“说出”的名称,因此保证不会与您的代码发生冲突。

总结

  我喜欢 C#。 它既舒适又令人兴奋,我喜欢看看接下来会发生什么。 我希望这一章已经把这种兴奋传递给了你。 但这只是一种味道。 让我们毫不拖延地进入这本书的真正业务。

你可能感兴趣的:(c#,c#)