用了WPF开发了一阵子,使用过程中许多知识点都绕不开一个词“.NET”,项目过程中还有配置框架“.NETCore”和“.NETFramework”,这使我不禁产生了疑问,所谓的“.NET”究竟是个啥?
虽然随便百度一下,就可以大致知道它是微软的开发平台,但还是想进一步的对它有个认知。
看到长长的目录不要慌,我建议看一下标‘*’的小节就好。
于是,翻开了微软官方文档,来学习总结一下(主要是结合文档翻译,加入一些自己理解的形式)。
.NET是一个免费的,开源的用于构建各种应用的开发平台,可以开发的应用类型有:
上面列举了一些.NET平台主要支持的应用开发类型,当然其中很多应用类型我都不了解,甚至概念都不清楚。对于大部分开发者可能是Web应用、桌面应用用的比较多,不过这不重要。这么多类型至少说明了一点,.NET很强大,微软很强大。
在不同的应用和应用类型间通过类库进行功能的共享。
无论你是哪种应用,使用.NET可以让你的代码和工程看起来没有差别。你在不同应用程序中会访问同样的运行时库、API和语言功能。
我记得我早期学习编程的时候,别人就说Windows跨平台不太行。那么这节的介绍或许会刷新一下这个刻板印象,虽然我没实践过用windows的东西操作跨平台。
你可以为多种操作系统创建.NET应用程序,包括:
支持的处理器架构包括:
.NET可以让你使用指定平台的功能,比如操作系统的API接口。举例来说,在Windows系统下使用WinForms和WPF,在移动平台用Xamarin。(这个大概是说使用指定平台的指定框架开发,就可以很轻松地获得该平台的一些特性,比如用WinForms可以轻松在Windows系统上开发出GUI程序,所以它想说.NET为你提供了不同平台的强大开发环境支持)
额,这节的标题又是很具迷惑性。我记得早期接触编程,还经常有人跟我讲Windows的东西不开源,不好用。我不知道这连续的几个标题,是微软的自吹自擂,还是微软在多年来确实有改进,还是我被刻板印象所禁锢的很深呢?我想几者都有吧。
.NET是免费且开源的,使用MIT和Apache 2协议。.NET是.NET基金会的一个工程。
.NET由微软在Windows、macOS和Linux进行支持。它每个月的第二个周二会进行定期的在安全性和稳定性上的更新。
.NET二进制发行文件由微软在其服务器上构建且测试,并且遵循微软的工程和安全实践规范。
红帽(Red Hat,搞Linux操作系统的)也提供了对.NET的支持。红帽与微软合作来保证.NET Core在红帽的Linux系统上运行。
与红帽和微软的合作一样,泰泽(Tizen)也提供.NET在泰泽平台上的支持。
说实话,这节是我写这篇文的目的,我的初衷就是想了解一下 .NET Core是啥,和.NET Framework啥关系。
.NET具有不同的口味,确切地来说,.NET具有不同的实现方式。.NET 5+(包括.NET Core)是最新的实现,并且能够运行在任意平台。.NET Framework是.NET原始的实现,且只能运行在Windows上。Mono在需要小型运行环境时使用(这个我不懂,斗胆猜测一下是不是可裁剪之类的)。UWP(Universal Windows Platform)用于构建现代Windows应用程序(啥叫现代呢?我的理解是它可以在如pad、手机等各种现代设备上运行,当然是windows自己的设备,原先微软不是还做手机吗,叫WinPhone,现在貌似有点凉了)。
每种实现都包含了运行时环境和类库。也可能包含了应用框架和开发工具。
.NET标准不是.NET的一种具体实现,而是一种接口(API)规范能让你为.NET的多种实现(平台)开发类库。
所以,这短短一段下来,我的理解是.NET Framework是一种.NET标准的旧的实现,.NET Core比较新一些且跨平台(当然支持的功能应该是新的丰富一些),如果你全新开发一个项目,我觉得可能用新的.NET Core好些,如果维护旧项目,考虑到兼容性问题,应该是用老的.NET Framework。
工具和生产力并不冲突。.NET也给了你开发语言的选择,IDE(Integrated Development Environment,集成开发环境),和其他一些工具。
.NET支持三种编程语言:
下面有一些.NET语言支持的功能特性:
.NET的集成开发环境包括:
.NET SDK是一系列库和工具用于开发和运行.NET应用程序。
.当你下载.NET时,你可以选择SDK或者运行环境,如.NET运行环境或者ASP.NET Core运行环境。
为了运行.NET应用程序,你得在电脑上安装一个运行环境(它是一个用于管理程序的执行环境,直译有时候显得啰嗦且拗口,简单讲就是你为了要跑.NET程序就要装其运行环境)
若你想要在电脑上做开发,那你就得安装SDK。当你下载SDK时,你可以自动获得运行环境
Notes:
这边可以看出来,runtime(运行环境或者说运行库)和SDK(开发工具套件)是两种东西。前者是用来跑该平台程序的,后者就是用来开发程序的。但似乎前者一般是必须的。
SDK下载文件包括以下组件:
在我看来,project = 工程(一个个的那种工程) = 项目。
.NET应用程序的源码用MSBuild构建。项目文件(.csproj,.fsproj,.vbproj)指定了负责编译、打包和发布代码的目标和相关任务。其中有一些用于引用目标和任务的标准集合的SDK标识符。这些标识符的使用有助于保持项目文件的简洁且易于处理。例如,下面是一个控制台程序的项目文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>ExeOutputType>
<TargetFramework>net6.0TargetFramework>
PropertyGroup>
Project>
下面还有一个web程序的:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0TargetFramework>
PropertyGroup>
Project>
在这些例子中,工程元素(
略
这节与.NET是啥关系不大,但是NuGet这个工具真是太好用了。NuGet工具包就像个百宝箱,巨好用。我以前在其他平台开发,如果想要使用一些插件、类库,就需要去网上找,去Github上下源码编译集成到项目中。这个NuGet将这些操作全部集成到IDE了,你只需要打开NuGet包管理工具,一搜,找到后,添加就可以用了。
NuGet是一个为.NET而设计的开源包管理工具。NuGet包是一个拓展名为.nupkg的.zip文件,它包含了已编译的源码(DLLs),其他与代码相关的文件,一些包含版本号等信息的描述性的清单。代码开发者可以共享包并将它们发布到nuget.org或者私人主机上。那些想要使用它们的开发者只需要将包添加到工程,接着在项目代码中调用包中暴露的接口即可。
.NET交互是一个CLI工具和API的群组,它能使用户在网上、markdown、笔记上创建交互体验。
.NET应用程序在一个叫做CLR的运行时环境上面运行代码。
.NET CLR(Common Language Runtime,公共语言运行环境,毕竟上面说了嘛,.NET支持三种语言C#、F#、VB,那使得三种语言互通就需要这样一个CLR了)是一个跨平台运行时环境,它包含了对Windows、macOS和Linux的支持。CLR处理了内存的分配与管理。CLR也是一个虚拟机,它不仅执行应用程序,也使用JIT(Just-In-Time)编译器的生成和编译代码。(有点类似Java中的JVM吧)
说实话,看到这里,我觉得对.NET平台已经有个大致的认识了。接下来各种编译器、组成模块,我感觉一般应用开发不会涉及太多。但本着一文写完的原则,我觉得还是得往下写。
高层级的.NET语言,如C#,可以编译成无关硬件的指令集,称为中间语言(Intermediate Language,简称IL)。当应用程序运行时,JIT编译器将IL翻译成机器码以便处理器能够理解。JIT编译发生在代码将要运行的同一台机器上。(因为越底层,往往与硬件关系越紧密,C#是很“高级”的语言,所以它的整个翻译操作主要是软件层面的,与硬件关联度没那么高)
由于JIT编译发生在程序执行期间,所以编译的时间也是运行时间的一部分(这或许一定程度上可以解释大家说的高级语言,效率相对低下吧,因为在执行时加入了额外的时间)。因此,JIT编译器不得不去平衡优化代码所花的时间和结果生成代码生成所节约的时间。但是JIT编译器了解实际的硬件,并且能够解放不同平台需要不同实现的开发者。
.NET JIT编译器可以分层编译,这意味着它可以在运行时重新编译单个方法。这个特性使得它能快速编译的同时还能为频繁使用的方法生成高度调优的代码版本。(我的理解是,因为JIT能单独编译某个函数,如果你代码频繁改动某个函数,它不会去将工程整体编译,而只重新编译部分,所以使得编译速度也不慢)
略
GC(Garbage Collector,垃圾收集器)为应用程序管理着内存的分配与释放。每当你的代码生成一个新的对象,CLR都会在托管堆上为这个对象分配内存。只要托管堆上的地址空间可用(有足够的剩余空间),运行环境就会持续为新对象分配控件。当没有足够的剩余空间时,GC就会检查托管堆中是不是有程序不再使用的对象。接着,它会回收那些对象的空间。
GC是CLR服务的一部分,它有益于确保内存安全。若一个程序只会访问分配了的内存空间,那就称它为内存安全的。例如,运行环境会确保应用程序不会访问超出数组界限的那部分未被分配的内存。
这点也挺重要的,如果像C、C++那样随意访问,很容易出错。
略
略
略
略
.NET提供了对象/关系映射器(Object/Relational Mapper)和一种在代码中写SQL查询的方式。
Entity Framework(EF) Core是一种开源且跨平台数据访问技术,它可以用作ORM。EF Core使你可以在代码中用.NET对象来操作数据库。它减少了你操作数据库的代码量。并且它支持多种数据库引擎。
LINQ(Language-Integrated Query,语言集成查询)使你可以编写操作数据的声明性代码。数据可以是多种形式(如内存对象、SQL数据库或者XML文档),但你写的LINQ代码通常不会因为数据源的不同而不同。
为了更好地读懂.NET文档,了解一些术语的由来会对你有所帮助。
2002年,微软发布了.NET Framework,这是一个用于创建Windows应用的开发者平台。今天,.NET Framework已经是4.8版本了,并且微软仍然在对它进行支持。
2014年,微软引入了.NET Core,它是跨平台且开源的,同时也是.NET Framework的继承者。这种.NET的新实现在3.1版本时保留了.NET Core的名称。.NET Core 3.1之后的版本则被命名为了.NET 5。所以.NET 5+(此处‘+’表示之后版本的意思)和.NET Core 指的是.NET的同一种实现。
为了避免混淆,在.NET Framework和.NET Core/5+之间的版本号4被跳过了。“.NET Core”中的 “Core”是为了使得现在的这种实现,明确地被认为是主要的。“Core”的命名法也保留在了ASP .NET Core和Entity Framework Core中。
文档也还是引用了.NET标准。且.NET标准仍是允许你为.NET的不同实现开发类库的API规范。
有些.NET的术语会被混淆,因为同一个词在不同场景中用到。下面列举了一些明显的例子:
语境 | runtime含义 |
---|---|
Common Language Runtime(CLR) | 指的是托管程序的执行环境。操作系统是运行环境(runtime)的一部分,但不是.NET runtime的一部分 |
在.NET下载页当中的.NET runtime | CLR和runtime libraries,这两者都提供了对运行框架依赖的程序的支持。页面也提供了runtime的选择(ASP .NET Core服务器程序还是Windows桌面程序) |
Runtime Identifier(RID) | .NET程序运行的操作系统和CPU架构。例如:Windows x64,Linux x64 |
语境 | 含义 |
---|---|
.NET Framework | 最原始的,只支持Windows系统的.NET实现。此处Framework的F是大写的 |
target framework | .NET程序或者库依赖的API集。如:.NET Core 3.1,.NET Standard 2.0 |
Target Framework Moniker(TFM) | TFM是一种标准的令牌格式,用于指定.NET程序或库的目标框架。如:net462表示.NET Framework 4.6.2。 |
framework-dependent app | 这里framework的用法和你从.NET下载页上下载的runtime的用法一样(就是那些开发&运行环境) |
framework libraries | 有时也写作runtime libraries,运行时库 |
语境 | 含义 |
---|---|
在.NET下载页中的SDK | 指的是你下载安装用于开发运行.NET程序的工具&库的集合。包括了CLI、MSBuild、.NET runtime和其他组件 |
SDK-style项目 | 一组用于指定怎样为特定程序类型构建项目的MSBuild目标和任务。这里的SDK指的是工程文件中 |
语境 | 含义 |
---|---|
cross platform | 程序运行所在的操作系统和硬件,例如:Windows、macOS、iOS和Android |
.NET platform | 这个含义有多重。可能专指.NET(如.NET Framework或.NET 5+),也可以指整个.NET平台 |
首字母缩写 | 含义 |
---|---|
Command Line Interface | 用于开发、构建、运行和发布.NET程序的一套跨平台工具链 |
Common Language Infrastructure | CLR实现 |
以下片段解释了.NET在高级场景中的一些功能。
所有操作系统都会包含一些API(Application Programming Interface)以提供系统服务。.NET提供了以下几种方式来调用API。
与本地API交互的主要方式是通过“平台调用”,简称“P/Invoke”。“P/Invoke”受Linux和Windows平台支持。一种仅适用在Windows平台的交互方式叫“COM interop”(组件交互),它使用托管代码中的COM组件。它构建在P/Invoke的基础结构之上,但是工作方式略有不同。
靠着语言支持,CLR使你能够通过非安全代码访问本地内存并且做一些指针运算。在某些算法和系统交互时需要这些操作。尽管可以支持非安全代码,但并不鼓励这么做,除非你为了效率不得不这么做。非安全代码在不同环境可能不会有相同的执行方式,并且会逝去GC和类型安全这两点好处。建议尽可能的将非安全代码集中管理,并且做足够多的测试。
终于写完了。我相信新手如果完完全全地看下来,对.NET会有一个比较全面的认识了。这篇文我也是结合文档花了一个上午写完的。虽然条目很多,但都是概念性的东西,粗略地看一下即可。
微软官方文档