使用 .NET CORE专业代码是几位数优先相同的类不能生成多张表

什么是.NET什么是.NET Framework?本文将从上往下,循序渐进的介绍一系列相关.NET的概念先从类型系统开始讲起,我将通过跨语言操作这个例子来逐渐引入一系列.NET的相关概念这主要包括:CLS、CTS(CLI)、FCL、Windows下CLR的相关核心组成、Windows下托管程序运行概念、什么是.NET Framework,.NET Core.NET Standard及一些VS编译器相关杂项和相关阅读链接。完整的从上读到下则你可以理解個大概的.NET体系

文章是我一字一字亲手码出来的,每天下班用休息时间写一点持续了二十来天。且对于文章上下衔接、概念引入花了很哆心思致力让很多概念在本文中显得通俗。但毕竟.NET系统很庞大本文篇幅有限,所以在部分小节中我会给出延伸阅读的链接在文章结尾我给出了一些小的建议,希望能对需要帮助的人带来帮助如果想与我交流可以文章留言或者加.NET技术交流群:

语言,是人们进行沟通表達的主要方式编程语言,是人与机器沟通的表达方式不同的编程语言,其侧重点不同有的编程语言是为了科学计算而开发的,所以其语法和功能更偏向于函数式思想有些则是为了开发应用程序而创立的,所以其语法和功能更为均衡全面

微软公司是全球最大的电脑軟件提供商,为了占据开发者市场进而在2002年推出了Visual Studio(简称VS,是微软提供给开发者的工具集) .NET 平台无缝集成的编程语言即C# 支持的编程语言,開发者就可以通过.NET平台提供的工具服务和框架支持便捷的开发应用程序

C#就是为宣传.NET而创立的,它直接集成于Visual Studio .NET中VB也在.NET 平台耦合度很高,並且.NET上的技术大多都是以C#编程语言为示例所以经常就.NET和C#混为一谈(实质上它们是相辅相成的两个概念)。
而作为一个开发者平台它不仅仅昰包含开发环境、技术框架、社区论坛、服务支持等,它还强调了平台的跨语言、跨平台编程的两个特性

跨平台:一次编译,不需要任哬专业代码是几位数修改应用程序就可以运行在任意有.NET框架实现的平台上,即专业代码是几位数不依赖于操作系统也不依赖硬件环境。

什么是跨语言互操作什么是CLS

每门语言在最初被设计时都有其在功能和语法上的定位,让不同的人使用擅长的语言去干合适的事这在團队协作时尤为重要。
.NET平台上的跨语言是通过CLS这个概念来实现的接下来我就以C#和VB来演示 什么是.NET中的跨语言互操作性。

通俗来说虽然c#和vb昰两个不同的语言,但此处c#写的类可以在vb中当做自家写的类一样正常使用

比如我在vb中写了一个针对String的首字母大写的扩展方法,将其编译後的dll引用至C#项目中

在C#项目中,可以像自身专业代码是几位数一样正常使用来自vb这个dll的扩展方法

现在有那么多面向对象语言,但不是所囿编程语言都能这样直接互操作使用而.NET平台支持的C#和VB之所以能这样无缝衔接,先读而后知后文将会介绍缘由。不过虽然.NET平台提供了这樣一个互操作的特性但终究语言是不一样的,每个语言有其特色和差异处在相互操作的时候就会难免遇到一些例外情况。

比如我在C#中萣义了一个基类类里面包含一个公开的指针类型的成员,我想在vb中继承这个类并访问这个公开的成员。

但是vb语言因为其定位不需要指針所以并没有C#中如int*这样的指针类型,所以在vb中访问一个该语言不支持的类型会报错的会提示:字段的类型不受支持。

再比如C#语言中,对类名是区分大小写的我在C#中定义了两个类,一个叫BaseBusiness另一个叫baseBusiness。我在vb中去继承这个BaseBusiness类

如图,在vb中访问这个类会报错的报:"BaseBusiness"不明确,这是因为在vb中对类名是不区分大小写的在vb中,它认为它同时访问了两个一模一样的类所以按照vb的规则这是不合理的。那么为了在vb调鼡c#的程序集中避免这些因语言的差异性而导致的错误在编写c#专业代码是几位数的时候 就应该提前知道vb中的这些规则,来应付式的开发 

泹是,如果我想不仅仅局限于C#和VB我还想我编写的专业代码是几位数在.Net平台上通用的话,那么我还必须得知道.NET平台支持的每一种语言和我編写专业代码是几位数所使用的语言的差异从而在编写专业代码是几位数中避免这些。

这几年编程语言层出不穷在将来.NET可能还会支持哽多的语言,如果说对一个开发者而言掌握所有语言的差异处这是不现实的所以.NET专门为此参考每种语言并找出了语言间的共性,然后定義了一组规则开发者都遵守这个规则来编码,那么专业代码是几位数就能被任意.NET平台支持的语言所通用

 CLS从类型、命名、事件、属性、數组等方面对语言进行了共性的定义及规范。这些东西被提交给欧洲计算机制造联合会ECMA称为:共同语言基础设施。

就以类型而言CLS定义叻在C#语言中符合规范的类型和不符合的有:

当然,就编码角度而言我们不是必须要看那些详略的文档。为了方便开发者开发.NET提供了一個特性,名叫:CLSCompliantAttribute专业代码是几位数被CLSCompliantAttribute标记后,如果你写的专业代码是几位数不符合CLS规范的话编译器就会给你一条警告。

值得一提的是CLS规则只是面向那些公开可被其它程序集访问的成员,如public、继承的protected对于该程序集的内部成员如Private、internal则不会执行该检测规则。也就是说所適应的CLS遵从性规则,仅是那些公开的成员而非私有实现。

那么有没有那种特殊情况比如我通过反射技术来访问该程序集中,当前语言並不拥有的类型时会发生什么情况呢

答案是可以尝试的,如用vb反射访问c#中的char*指针类型即使vb中没有char*这种等价的指针类型,但mscorlib提供了针对指针类型的 Pointer 包装类供其访问可以从运行时类携带的类型名称看到其原本的类型名。

可以看到该类中的元素是不符合CLS规范的。

提到特殊凊况还要说的一点就是异常处理。.NET框架组成中定义了异常类型系统在编译器角度,所有catch捕获的异常都必须继承自开发中编写跨语言組件时所遵循的那些共性,那些规范就叫做 Common Langrage Specification简称 CLS公共语言规范

如果理解了什么是CLS的话,那么你将很轻松理解什么是CTS
假设你已经围绕着葑装 继承 多态 这3个特性设计出了多款面向对象的语言,你发现大家都是面向对象都能很好的将现实中的对象模型表达出来。除了语法和功能擅长不同语言的定义和设计结构其实都差不多一回事。

比如现实中你看到了一辆小汽车,这辆车里坐着两个人那么如何用这门語言来表达这样的一个概念和场面?
首先要为这门语言横向定义一个“类型”的概念接下来在程序中就可以这样表示:有一个汽车类型,有一个人类型在一个汽车类型的对象内包含着两个人类型的对象,因为要表达出这个模型你又引入了“对象”的概念 。而现在你叒看到,汽车里面的人做出了开车的这样一个动作由此你又引入了“动作指令”这样一个概念。
接着你又恍然大悟总结出一个定理,無论是什么样的“类型”都只会存在这样一个特征,即活着的 带生命特征的(如人) 和 死的 没有生命特征的(如汽车) 这两者中的一个最后,隨着思想模型的成熟你发现,这个“类型”就相当于一个富有主体特征的一组指令的集合
好,然后你开始照葫芦画瓢你参考其它程序语言,你发现大家都是用class来表示类的含义用struct表示结构的含义,用new来表示 新建一个对象的含义于是,你对这部分功能的语法也使用class和new關键字来表示然后你又发现,他们还用很多关键字来更丰富的表示这些现实模型比如override、virtual等。于是在不断的思想升级和借鉴后,你对這个设计语言过程中思想的变化仔细分析对这套语言体系给抽象归纳,最终总结出一套体系

于是你对其它人这样说,我总结出了一门語言很多必要的东西如两种主要类别:值类别和引用类别五个主要类型:类、接口、委托、结构、枚举,我还规定了一个类型可以包含字段、属性、方法、事件等成员,我还指定了每种类型的可见性规则和类型成员的访问规则等等等等,只要按照我这个体系来设计语訁设计出来的语言它能够拥有很多不错的特性,比如跨语言跨平台等,C#和的语言时所需要遵循一个体系(.Net平台下的语言都支持的一个体系)这个体系就是CTS(Common Type System 公共类型系统)它包括但不限于:

  • 建立用于跨语言执行的框架。
  • 提供面向对象的模型支持在 .NET 实现上实现各种语言。
  • 萣义处理类型时所有语言都必须遵守的一组规则(CLS)
  • 提供包含应用程序开发中使用的基本基元数据类型(如 Boolean、Byte、Char 等)的库。

一个编程语言洳果它能够支持CTS,那么我们就称它为面向.NET平台的语言

微软已经将CTS和.NET的一些其它组件,提交给ECMA以成为公开的标准最后形成的标准称为CLI(Common Language Infrastructure)公共语言基础结构。
所以有的时候你见到的书籍或文章有的只提起CTS有的只提起CLI,请不要奇怪你可以宽泛的把他们理解成一个意思,CLI昰微软将CTS等内容提交给国际组织计算机制造联合会ECMA的一个工业标准

在CTS中有一条就是要求基元数据类型的类库。我们先搞清什么是类库類库就是类的逻辑集合,你开发工作中你用过或自己编写过很多工具类比如搞Web的经常要用到的 JsonHelper、XmlHelper、HttpHelper等等,这些类通常都会在命名为Tool、Utility等這样的项目中 像这些类的集合我们可以在逻辑上称之为 "类库",比如这些Helper我们统称为工具类库

什么是基础类库BCL?

当你通过VS创建一个项目後你这个项目就已经引用好了通过.NET下的语言编写好的一些类库。比如控制台中你直接就可以用ConSole类来输出信息或者using 的开发语言中使用的基本的功能,这部分类我们称之为BCL(Base Class Library), 基础类库它们大多都包含在System命名空间下。

基础类库BCL包含:基本数据类型文件操作,集合洎定义属性,格式设置安全属性,I/O流字符串操作,事件日志等的类型

什么是框架类库FCL

有关BCL的就不在此一一类举。.NET之大发展至今,甴微软帮助开发人员编写的类库越来越多这让我们开发人员开发更加容易。由微软开发的类库统称为:FCLFramework Class Library ,.NET框架类库我上述所表达的BCL僦是FCL中的一个基础部分,FCL中大部分类都是通过C#来编写的

在FCL中,除了最基础的那部分BCL之外还包含我们常见的 如 : 用于网站开发技术的 web api、Web Service類库等等

像上文在CTS中提到了 基本基元数据类型,大家知道每门语言都会定义一些基础的类型,比如C#通过 int 来定义整型用 string 来定义 字符串 ,鼡 object 来定义 根类当我们来描述这样一个类型的对象时可以有这两种写法,如图:

我们可以看到上边用首字母小写的蓝色体string、object能描述,用艏字母大写的浅蓝色String、Object也能描述,这两种表述方式有何不同

要知道,在vs默认的颜色方案中蓝色体 代表关键字,浅蓝色体 代表类型
那么這样也就意味着,由微软提供的FCL类库里面 包含了 一些用于描述数据类型的 基础类型无论我们使用的是什么语言,只要引用了FCL我们都可鉯通过new一个类的方式来表达数据类型。

用new来创建这些类型的对象但这样就太繁琐,所以C#就用 int关键字来表示的语言的基元类型与对应的BCL的類别图 :

的语言的类型根它是整个FCL的类型根。

   当然CTS定义了单继承,很多编程语言都满足这个规则但也有语言是例外,如C++就不做继承限制可以继承多个,C++/CLI作为C++在对.NET的CLI实现如果在非托管编码中多继承那也可以,如果试图在托管专业代码是几位数中多继承那就会报错。我前面已经举过这样特殊情况的例子这也在另一方面反映出,各语言对CTS的支持并不是都如C#那样全面的我们只需明记一点:对于符合CTS嘚那部分自然就按照CTS定义的规则来。 任何可遵循CTS的类型规范同时又有.NET运行时的实现的编程语言就可以成为.NET中的一员。

计算机是如何运行程序的

接下来我要说什么是.NET的跨平台,并解释为什么能够跨语言不过要想知道什么是跨平台,首先你得知道一个程序是如何在本机上運行的

CPU,全称Central Processing Unit,叫做中央处理器,它是一块超大规模的集成电路,是计算机组成上必不可少的组成硬件没了它,计算机就是个壳
无论你编程水平怎样,你都应该先知道CPU是一台计算机的运算核心和控制核心,CPU从存储器或高速缓冲存储器中取出指令放入指令寄存器,并对指囹译码执行指令。
我们运行一个程序CPU就会不断的读取程序中的指令并执行,直到关闭程序事实上,从电脑开机开始CPU就一直在不断嘚执行指令直到电脑关机。

在计算机角度每一种CPU类型都有自己可以识别的一套指令集,计算机不管你这个程序是用什么语言来编写的其最终只认其CPU能够识别的二进制指令集。
在早期计算机刚发展的时代人们都是直接输入这样的没有语义的二进制指令来让计算机工作的,可读性几乎没有没人愿意直接编写那些没有可读性、繁琐、费时,易出差错的二进制01专业代码是几位数所以后来才出现了编程语言。

编程语言的诞生使得人们编写的专业代码是几位数有了可读性,有了语义与直接用01相比,更有利于记忆
而前面说了,计算机最终呮识别二进制的指令那么,我们用编程语言编写出来的专业代码是几位数就必须要转换成供机器识别的指令

return 能让机器识别的二进制专業代码是几位数;

所以从一门编程语言所编写的专业代码是几位数文件转换成能让本机识别的指令,这中间是需要一个翻译的过程
而我们現在计算机上是运载着操作系统的,光翻译成机器指令也不行还得让专业代码是几位数文件转化成可供操作系统执行的程序才行。
那么這些步骤就是编程语言所对应的编译环节的工程了。这个翻译过程是需要工具来完成我们把它叫做 编译器。

不同厂商的CPU有着不同的指囹集为了克服面向CPU的指令集的难读、难编、难记和易出错的缺点,后来就出现了面向特定CPU的特定汇编语言 比如我打上这样的x86汇编指令 mov ax,bx ,然后用上用机器码做的汇编器它将会被翻译成 1000 这样的二进制01格式的机器指令.

不同CPU架构上的汇编语言指令不同,而为了统一一套写法哃时又不失汇编的表达能力,C语言就诞生了
用C语言写的专业代码是几位数文件,会被C编译器先转换成对应平台的汇编指令再转成机器碼,最后将这些过程中产生的中间模块链接成一个可以被操作系统执行的程序

那么汇编语言和C语言比较,我们就不需要去阅读特定CPU的汇編码我只需要写通用的C源码就可以实现程序的编写,我们用将更偏机器实现的汇编语言称为低级语言与汇编相比,C语言就称之为高级語言

在看看我们C#,我们在编码的时候都不需要过于偏向特定平台的实现翻译过程也基本遵循这个过程。它的编译模型和C语言类似都昰属于这种间接转换的中间步骤,故而能够跨平台
所以就类似于C/C#等这样的高级语言来说是不区分平台的,而在于其背后支持的这个 翻译原理 是否能支持其它平台

什么是托管专业代码是几位数,托管语言托管模块?

作为一门年轻的语言C#借鉴了许多语言的长处,与C比较C#则更为高级。
往往一段简小的C#专业代码是几位数其功能却相当于C的一大段专业代码是几位数,并且用C#语言你几乎不需要指针的使用這也就意味着你几乎不需要进行人为的内存管控与安全考虑因素,也不需要多懂一些操作系统的知识这让编写程序变得更加轻松和快捷。

如果说C#一段专业代码是几位数可以完成其它低级语言一大段任务那么我们可以说它特性丰富或者类库丰富。而用C#编程不需要人为内存管控是怎么做到的呢
    .NET提供了一个垃圾回收器(GC)来完成这部分工作,当你创建类型的时候它会自动给你分配所需要的这部分内存空间。就楿当于有一个专门的软件或进程,它会读取你的专业代码是几位数然后当你执行这行专业代码是几位数的时候,它帮你做了内存分配笁作 这部分本该你做的工作,它帮你做了这就是“托管”的概念。比如现实中 托管店铺、托管教育等这样的别人替你完成的概念

因此,C#被称之为托管语言C#编写的专业代码是几位数也就称之为托管专业代码是几位数,C#生成的模块称之为托管模块等。(对于托管的资源是鈈需要也无法我们人工去干预的,但我们可以了解它的一些机制原理在后文我会简单介绍。)

只要有比较就会产生概念。那么在C#角度那些脱离了.NET提供的诸如垃圾回收器这样的环境管制,就是对应的 非托管了

我们编写的程序有的模块是由托管专业代码是几位数编写,有嘚模块则调用了非托管专业代码是几位数在.NET Framework中也有一套基于此操作系统SEH的异常机制,理想的机制设定下我们可以直接通过catch(e)或catch来捕获指定嘚异常和框架设计人员允许我们捕获的异常

而异常类型的级别也有大有小,有小到可以直接框架本身或用专业代码是几位数处理的有夶到需要操作系统的异常机制来处理。.NET会对那些能让程序崩溃的异常类型给进行标记对于这部分异常,在.NET Framework 虚拟机

实际上,.NET不仅提供了洎动内存管理的支持他还提供了一些列的如类型安全、应用程序域、异常机制等支持,这些 都被统称为CLR公共语言运行库

CLR是.NET类型系统的基础,所有的.NET技术都是建立在此之上熟悉它可以帮助我们更好的理解框架组件的核心、原理。
在我们执行托管专业代码是几位数之前總会先运行这些运行库专业代码是几位数,通过运行库的专业代码是几位数调用从而构成了一个用来支持托管程序的运行环境,进而完荿诸如不需要开发人员手动管理内存一套专业代码是几位数即可在各大平台跑的这样的操作。

这套环境及体系之完善以至于就像一个尛型的系统一样,所以通常形象的称CLR为".NET虚拟机"那么,如果以进程为最低端进程的上面就是.NET虚拟机(CLR),而虚拟机的上面才是我们的托管专業代码是几位数换句话说,托管程序实际上是寄宿于.NET虚拟机中

什么是CLR宿主进程,运行时主机

那么相对应的,容纳.NET虚拟机的进程就是CLR宿主进程了该程序称之为运行时主机。

这些运行库的专业代码是几位数全是由C/C++编写,具体表现为以 Framework 语言编写存储过程、触发器、用户萣义类型、用户定义函数(标量函数和表值函数)以及用户定义的聚合函数

Windows系统默认安装的有.NET Framework,并且可以安装多个.NET Framework版本你也不需要因此卸载,因为你使用的应用程序可能依赖于特定版本如果你移除该版本,则应用程序可能会中断



如何确认本机安装了哪些.NET Framework和对应CLR的版夲?

我们可以通过注册表等其它方式来查看安装的最新版本: 
不过如果不想那么复杂的话,还有种最直接简单的:
那就是进入该目录文件夹随便找到几个文件对其右键,然后点击详细信息即可查看到对应的文件版本可以依据文件版本估摸出.NET Framework版本,比如 Framework目录文件夹中就附带的有 用于C#语言的命令行形式的编译器下的一些数据类型)、Environment类(提供有关当前环境和平台的信息以及操作它们的方法)、Console类(用于控制台输入輸出等)、Socket系列类(对tcp协议抽象的接口)、File文件系列类(对文件目录等操作系统资源的一些操作)、Encoding类(字符流的编码)等
这些类都属于BCL中的一部分,咜们存在但不限于程序执行原理

好的现在我们已经有了一个中,使用 Native可以提前将专业代码是几位数编译成本机指令

Ngen是将IL专业代码是几位数提前给全部编译成本机专业代码是几位数并安装在本机的本机映像缓存中,故而可以减少程序因JIT预热的时间但同样的也会有很多注意事项,比如因JIT的丧失而带来的一些特性就没有了如类型验证。Ngen仅是尽可能专业代码是几位数提前编译程序的运行仍需要完整的CLR来支歭。

.NET Native在将IL转换为本机专业代码是几位数的时候会尝试消除所有元数据将依靠反射和元数据的专业代码是几位数替换为静态本机专业代码昰几位数,并且将完整的CLR替换为主要包含垃圾回收器的重构运行时mrt100_ Native: 

现在我们可以通过ILDASM工具(一款查看程序集IL专业代码是几位数的软件,在Microsoft SDKs目录中的子目录中)来查看该程序集的元数据表和Main方法中间码

c#源码第一行专业代码是几位数:string rootDirectory = 有个专门的概念定义,我们称为 程序集的加載方式

对于自身程序集内定义的类型,我们可以直接从自身程序集中的元数据中获取对于在其它程序集中定义的类型,CLR会通过一组规則来在磁盘中找到该程序集并加载在内存

CLR在查找引用的程序集的位置时候,第一个判断条件是 判断该程序集是否被签名

就比如大家都叫张三,姓名都一样喊一声张三不知道到底在叫谁。这时候我们就必须扩展一下这个名字以让它具有唯一性

我们可以通过 Framework /编程中必不鈳少的一部分,几尽每个项目都会引用为了不再每次使用的时候都复制一份,所以计算机上有一个位置专门存储这些我们都会用到的程序集叫做全局程序集缓存(Global Assembly

简单延伸两个问题,虚拟机CLR上的而在CLR中管控的这部分资源中,被分成了一个个逻辑上的分区这个逻辑分区被称为应用程序域,是.NET Framework中定义的一个概念
因为堆内存的构建和删除都通过GC去托管,降低了人为出错的几率在此特性基础上.NET强调在一个進程中通过CLR强大的管理建立起对资源逻辑上的隔离区域,每个区域的应用程序互不影响从而让托管专业代码是几位数程序的安全性和健壯性得到了提升。

熟悉程序集加载规则和AppDomain是在.NET技术下进行插件编程的前提AppDomain这部分概念并不复杂。
当启动一个托管程序时最先启动的是CLR,在这过程中会通过专业代码是几位数初始化三个逻辑区域最先是SystemDomain系统程序域,然后是SharedDoamin共享域最后是{程序集名称}Domain默认域。

系统程序域裏维持着一些系统构建项我们可以通过这些项来监控并管理其它应用程序域等。共享域存放着其它域都会访问到的一些信息当共享域初始化完毕后,会自动加载技术进行插件编程

当我们想让程序在不关闭不重新部署的情况下添加一个新的功能或者改变某一块功能,我們可以这样做:将程序的主模块仍默认加载至默认域再创建一个新的应用程序域,然后将需要更改或替换的模块的程序集加载至该域烸当更改和替换的时候直接卸载该域即可。 而因为域的隔离性我在A域和B域加载同一个程序集,那么A域和B域就会各存在内存地址不同但数據相同的程序集数据

事实上,在开发中我们还应该注意跨域访问对象的操作(即在A域中的程序集专业代码是几位数直接调用B域中的对象)是與平常编程中有所不同的一个域中的应用程序不能直接访问另一个域中的专业代码是几位数和数据,对于这样的在进程内跨域访问操作汾两类

一是按引用封送,需要继承/zh-cn/library/中内存区域分为堆栈和托管堆。

堆和堆栈就内存而言只不过是地址范围的区别不过堆栈的数据结構和其存储定义让其在时间和空间上都紧密的存储,这样能带来更高的内存密度能在CPU缓存和分页系统表现的更好。故而访问堆栈的速度總体来说比访问堆要快点

操作系统会为每条线程分配一定的空间,Windwos为1M这称之为线程堆栈。在CLR中的栈主要用来执行线程方法时保存临時的局部变量和函数所需的参数及返回的值等,在栈上的成员不受GC管理器的控制它们由操作系统负责分配,当线程走出方法后该栈上荿员采用后进先出的顺序由操作系统负责释放,执行效率高
而托管堆则没有固定容量限制,它取决于操作系统允许进程分配的内存大小囷程序本身对内存的使用情况托管堆主要用来存放对象实例,不需要我们人工去分配和释放其由GC管理器托管。

为什么值类型存储在栈仩

不同的类型拥有不同的编译时规则和运行时内存分配行为我们应知道,C# 是一种强类型语言每个变量和常量都有一个类型,在.NET中每種类型又被定义为值类型或引用类型。

使用 struct、enum 关键字直接派生于中堆完全由CLR托管,也就是说GC堆是如何具体来释放的呢

当GC堆需要进行清悝的时候,GC收集器就会通过一定的算法来清理堆中的对象并且版本不同算法也不同。最主要的则为Mark-Compact标记-压缩算法
这个算法的大概含义僦是,通过一个图的数据结构来收集对象的根这个根就是引用地址,可以理解为指向托管堆的这根关系线当触发这个算法时,会检查圖中的每个根是否可达如果可达就对其标记,然后在堆上找到剩余没有标记(也就是不可达)的对象进行删除这样,那些不在使用的堆中對象就删除了

前面说了,因为nextObjPtr的缘故在堆中分配的对象都是连续分配的,因为未被标记而被删除那么经过删除后的堆就会显得支零破碎,那么为了避免空间碎片化所以需要一个操作来让堆中的对象再变得紧凑、连续,而这样一个操作就叫做:Compact压缩
而对堆中的分散嘚对象进行挪动后,还会修改这些被挪动对象的指向地址从而得以正确的访问,最后重新更新一下nextObjPtr指针周而复始。

而为了优化内存结構减少在图中搜索的成本,GC机制又为每个托管堆对象定义了一个属性将每个对象分成了3个等级,这个属性就叫做:代0代、1代、2代。

烸当new一个对象的时候该对象都会被定义为第0代,当GC开始回收的时候先从0代回收,在这一次回收动作之后0代中没有被回收的对象则会被定义成第1代。当回收第1代的时候第1代中没有被清理掉的对象就会被定义到第2代。
CLR初始化时会为0/1/2这三代选择一个预算的容量0代通常以256 KB-4 MBの间的预算开始,1代的典型起始预算为512 KB-4 MB2代不受限制,最大可扩展至操作系统进程的整个内存空间

比如第0代为256K,第1代为2MB我们不停的new对潒,直到这些对象达到256k的时候GC会进行一次垃圾回收,假设这次回收中回收了156k的不可达对象剩余100k的对象没有被回收,那么这100k的对象就被萣义为第1代现在就变成了第0代里面什么都没有,第1代里放的有100k的对象这样周而复始,GC清除的永远都只有第0代对象除非当第一代中的對象累积达到了定义的2MB的时候,才会连同清理第1代然后第1代中活着的部分再升级成第二代...

第二代的容量是没有限制,但是它有动态的阈徝(因为等到整个内存空间已满以执行垃圾回收是没有意义的)当达到第二代的阈值后会触发一次0/1/2代完整的垃圾收集。

也就是说代数越长說明这个对象经历了回收的次数也就越多,那么也就意味着该对象是不容易被清除的
这种分代的思想来将对象分割成新老对象,进而配對不同的清除条件这种巧妙的思想避免了直接清理整个堆的尴尬。

GC收集器会在第0代饱和时开始回收托管堆对象对于那些已经申明或绑萣的不经访问的对象或事件,因为不经常访问而且还占内存(有点懒加载的意思)所以即时对象可达,但我想在GC回收的时候仍然对其回收當需要用到的时候再创建,这种情况该怎么办

那么这其中就引入了两个概念:
对于这2两个不区分语言的共同概念,大家可自行扩展百度此处就不再举例。

那么除了通过new对象而达到代的阈(临界)值时还有什么能够导致垃圾堆进行垃圾回收呢? 还可能windows报告内存不足、CLR卸载AppDomain、CLR關闭等其它特殊情况

或者,我们还可以自己通过专业代码是几位数调用

.NET有GC来帮助开发人员管理内存,并且版本也在不断迭代GC帮我们託管内存,但仍然提供了平台的P/Invoke或COM技术(微软为CLR定义了COM接口并在注册表中注册)来调用

像FCL中的源码,很多涉及到操作系统的诸如 文件句柄、網络连接等外部extren的底层方法都是非托管语言编写的对于这些非托管模块所占用的资源,我们可以通过隐式调用析构函数(Finalize)或者显式调用的Dispose方法通过在方法内部写上非托管提供的释放方法来进行释放

像文中示例的socket就将释放资源的方法写入Dispose中,析构函数和Close方法均调用Dispose方法以此唍成释放事实上,在FCL中的使用了非托管资源的类大多都遵循IDispose模式而如果你没有释放非托管资源直接退出程序,那么操作系统会帮你释放该程序所占的内存的

还有一点,垃圾回收是对性能有影响的
GC虽然有很多优化策略,但总之只要当它开始回收垃圾的时候,为了防圵线程在CLR检查期间对对象更改状态所以CLR会暂停进程中的几乎所有线程(所以线程太多也会影响GC时间),而暂停的时间就是应用程序卡死的时間为此,对于具体的处理细节GC提供了2种配置模式让我们选择。

第一种为:单CPU的工作站模式专为单CPU处理器定做。这种模式会采用一系列策略来尽可能减少GC回收中的暂停时间
而工作站模式又分为并发(或后台)与不并发两种,并发模式表现为响应时间快速不并发模式表现為高吞吐量。

第二种为:多CPU的服务器模式它会为每个CPU都运行一个GC回收线程,通过并行算法来使线程能真正同时工作从而获得性能的提升。

我们可以通过在Config文件中更改配置来修改GC模式如果没有进行配置,那么应用程序总是默认为单CPU的工作站的并发模式并且如果机器为單CPU的话,那么配置服务器模式则无效

虽然我们可以选择适合的GC工作模式来改善垃圾回收时的表现,但在实际开发中我们更应该注意减少鈈必要的内存开销

几个建议是,减换需要创建大量的临时变量的模式、考虑对象池、大对象使用懒加载、对固定容量的集合指定长度、紸意字符串操作、注意高频率的隐式装箱操作、延迟查询、对于不需要面向对象特性的类用static、需要高性能操作的算法改用外部组件实现(p/invoke、com)、减少throw次数、注意匿名函数捕获的外部对象将延长生命周期、可以阅读GC相关运行时配置在高并发场景注意变换GC模式...

至此.NET Framework上的三个重要概念,程序集、应用程序域、内存在本文讲的差不多了我画了一张图简单的概述.NET程序的一个执行流程:

对于后文,我将单独的介绍一些其咜杂项首先是.NET平台的安全性。

.NET Framework中的安全机制分为 基于角色的安全机制 和 专业代码是几位数访问安全机制

基于角色的安全机制作为传统嘚访问控制,其运用的非常广泛如操作系统的安全策略、数据库的安全策略等等...它的概念就相当于我们经常做的那些RBAC权限管理系统一样,用户关联角色角色关联权限,权限对应着操作
整个机制的安全逻辑就和我们平时编写专业代码是几位数判断是一样的,大致可以分為两个步骤.

第一步就是创建一个主体然后标识这个主体是什么身份(角色) ,第二步就是 身份验证也就是if判断该身份是否可以这样操作。

洏在.NET Framework中这主体可以是Windows账户,也可以是自定义的标识通过生成如当前线程或应用程序域使用的主体相关的信息来支持授权。
比如构造┅个代表当前登录账户的主体对象WindowsPrincipal,然后通过 Framework基于角色的安全性的详细的介绍感兴趣可以去了解 

专业代码是几位数访问安全性在.NET Framework中是用來帮助限制专业代码是几位数对受保护资源和操作的访问权限。
举个例子我通过创建一个FileIOPermission对象来限制对后续专业代码是几位数对D盘的文件和目录的访问,如果后续专业代码是几位数对D盘进行资源操作则报错 

为了确定专业代码是几位数是否有权访问某一资源或执行某一操莋,CLR的安全系统将审核调用堆栈以将每个调用方获得的权限与要求的权限进行比较。 如果调用堆栈中的任何调用方不具备要求的权限則会引发安全性异常并拒绝访问。

而除了Permissions权限专业代码是几位数访问安全性机制还有 权限集、证据、专业代码是几位数组、策略等概念。这些概念让CAS如此强大但相应的,它们也让CAS变得复杂必须为每个特定机器定义正确的PermissionSet和Code Groups才能设置成一个成功的CAS策略。

考虑到这层原因Microsoft .NET安全小组决定从头开始重建专业代码是几位数访问安全性。在.NET Framework 平台上的安全机制仅仅是.NET平台上的,因此它只限制于托管专业代码是几位数我们可以直接调用非托管专业代码是几位数或进程通信间接调用非托管专业代码是几位数等多个手段来突破对托管专业代码是几位數 操作资源的限制。

事实上我们在平常项目中专业代码是几位数编写的安全机制(业务逻辑身份验证、项目框架验证)与这些平台级的安全機制没什么不同。我们可以理解为专业代码是几位数写的位置不一样.NET安全机制是写在CLR组件中,而我们的安全机制是写在上层的专业代码昰几位数中这些平台级的标识更多的是和操作系统用户有关,而我们项目专业代码是几位数中的标识则是和在数据库中注册的用户有关 大家都是通过if else来去判断,判断的主体和格局不一样逻辑本质都是相同的。

NET Core不支持专业代码是几位数访问安全性和安全性透明性

.NET是一個微软搭造的开发者平台,它主要包括:

    • 下的语言运行时的环境:CLR
    • 事实上像我上面讲的那些诸如程序集、GC、AppDomain这样的为CLR的一些概念组成,實质上指的是.NET Framework CLR

      .NET平台是微软为了占据开发市场而成立的,不是无利益驱动的纯技术平台的那种东西基于该平台下的技术框架也因为 商业間的利益 从而和微软自身的Windows操作系统所绑定。所以虽然平台雄心和口号很大但很多框架类库技术都是以Windows系统为蓝本,这样就导致虽然.NET各方面都挺好,但是用.NET就必须用微软的东西直接形成了技术-商业的绑定。

      最为关键的是pdb符号文件没得符号就调不了,对于符号我们从微软的符号服务器上下载(默认就已配置)还得有源专业代码是几位数来调试。

      点击工具-选项-调试-常规如果你之前没有在该配置栏配置过,那么你就勾选 启用源服务器支持 、启用.net Framework源专业代码是几位数单步执行然后将 要求源文件与原始版本完全匹配 给取消掉。

      然后就是下载pdb苻号文件了如果想直接下载那么可以在调试-符号这栏 将Microsoft符号服务器给勾上 。如果想按需下载那么在调试的时候,可以点击调试-窗口 选擇 模块/调用堆栈 来选择自己想加载的去加载

      然后至 网站 点击右上角下载源专业代码是几位数。当你调试专业代码是几位数的时候会提礻你无可用源,这个时候你再将你下载下来的源码文件给浏览查找一下就可以了

      还一种方法是,下载.NET Reflector插件该插件可以帮助我们在VS中直接调试dll,这种方式操作非常简单不过该插件收费,具体的可以查看我之前写过的文章(群里有该插件的注册版)

      有丑才有美有低才有高,概念是比较中诞生的.NET Core就是如此,它是其它操作系统的.NET Framework翻版实现

      我们知道,一个.NET程序运行核心在于.NET CLR为了能让.NET程序在其它平台上运行,┅些非官方社区和组织为此开发了在其它平台下的.NET实现(最为代表的是mono其团队后来又被微软给合并了 ),但因为不是官方所以在一些方面多少有些缺陷(如FCL),后来微软官方推出了.NET Core其开源在Github中,并被收录在NET基金会(.NET Foundation由微软公司成立与赞助的独立自由软件组织,其目前收录包括.NET编译器平台("Roslyn")以及 CoreXamarin Forms以及其它流行的.NET开源框架),旨在真正的 .NET跨平台

      这份工作仍然是巨大的,因为在早期对.NET上的定义及最初的实现一直昰以Windows系统为参照及载体一些.NET机制实际上与Windows系统耦合度非常高,有些属于.NET自己体系内的概念有些则属于Windows系统api的封装。 那么从Windows转到其它平囼上不仅要实现相应的CLR,还要舍弃或重写一部分BCL因而,.NET Core在概念和在项目中的行为与我们平常有些不同

      比如,NET Core不支持AppDomains、远程处理、专業代码是几位数访问安全性 (CAS) 和安全透明度任何有关该概念的库专业代码是几位数都应该被替换。
      这部分专业代码是几位数它不仅指你项目中的专业代码是几位数还指你项目中using的那些程序集专业代码是几位数,所以你会在github上看到很多开源项目都在跟进对.NET Core的支持,并且很多开發者也尝试学习.NET Core这也是一种趋势。

      值得一提的是微软还为BCL提出了一个标准毕竟各式各样的平台,技术层出不穷为了防止.NET在类库方面嘚碎片化,即提出了一套正式的 .NET API (.NET 的应用程序编程接口)规范.NET Standard。

      正如上面CLS一样.NET Standard就类似于这样的一个概念,无论是哪个托管框架我们遵循這个标准,就能始终保持在BCL的统一性即我不需要关心我是用的.NET Framework还是.NET Core,只要该类被定义于.NET Standard中我就一定能在对应支持的.NET Standard的版本的托管框架Φ找到它。

      .NET官方开源项目链接

      现在我将给出.NET相关的开源项目地址:
      参与.NET和.NET开源项目的起点:

      • 一些常用框架对 Core的支持报告:
      • 一些.NET下用于支持開发的开源项目集合:
      • 微软出品的分布式框架orleans:
      • 的开源和跨平台机器学习框架:

      在文章最后我还要简单的说下Visual Studio。

      通过上文得知只需要┅个txt记事本+程序,那么与之相比.NET提供的开发工具VS有什么不同呢?

      我们用记事本+程序只适合小打小闹对于真正要开发一个项目而言,我們需要文件管理、版本管理、一个好的开发环境等而vs ide则就是这样一个集成专业代码是几位数编辑、编译、调试、追踪、测试、部署、协莋、插件扩展这样多个组件的集成开发环境,的命令(Sql查询语句...)、ASP.NET相关事件、专业代码是几位数发送的HTTP请求、程序集加载卸载事件、文件访問打开关闭事件、Winform/Webform/WPF动作事件、线程事件、环境变量、Console/Trace等输出...

      我们可以通过在调试状态下点击调试菜单-窗口-显示诊断工具或者直接按Ctrl+Alt+F2来唤起该功能窗口。

      当然VS还有其它强大的功能,我建议大家依次点完 菜单项中的 调试、体系结构、分析这三个大菜单里面的所有项你会发現VS真是一个强大的IDE。比较实用且方便的功能举几个例子:

      比如 从专业代码是几位数生成的序列图该功能在vs2015之前的版本可以找到( 、)

      比如 模塊关系的专业代码是几位数图,可以看到各模块间的关系 

      比如 对解决方案的专业代码是几位数度量分析结果 

      比如 调试状态下 函数调用的 专業代码是几位数图我们可以看到MVC框架的函数管道模型

      以及并行堆栈情况、加载的模块、线程的实际情况

      还有如进程、内存、反汇编、寄存器等的功能,这里不再一一展示

      有关项目模板: 
      有关项目元素的说明介绍:

}

什么是MVC (模型 视图 控制器)?

MVC是一个架構模式它分离了表现与交互。它被分为三个核心部件:模型、视图、控制器下面是每一个部件的分工:

  • 视图是用户看到并与之交互的堺面。
  • 模型表示业务数据并提供数据给视图。
  • 控制器接受用户的输入并调用模型和视图去完成用户的需求

图: MVC (模型、视图、控制器)

你能解释下MVC的完整流程吗?

下面是MVC(模型、视图、控制器)架构的控制流程:

  • 所有的终端用户请求被发送到控制器
  • 控制器依赖请求去选择加載哪个模型,并把模型附加到对应的视图
  • 附加了模型数据的最终视图做为响应发送给终端用户。

使用MVC有哪些好处?

MVC有两个大的好处:

  • 分离叻关注点后台专业代码是几位数被移到单独的类文件,我们可以最大限度的重复利用专业代码是几位数
  • 自动化UI测试成为可能,因为后囼专业代码是几位数移到了.NET类这让我们更容易做单元测试和自动化测试。

MVC不同于三层架构

MVC是三层传统架构的演变。三层架构和MVC有一些通用的组成部分 显示如下:

MVC的最新版本是哪个?

我们也需要创建一个controller,去验证用户如果验证通过,需要设置cookies值

if ((中添加引用,那么SOAP是最簡单的方式
WebAPI的输出是简单的字符串、JSON、简单XML格式等。所以写解析逻辑非常简单。

在MVC中我们如何识别是PSOT还是GET调用

什么是MVC中的打包也压縮?

打包与压缩帮助我们减少一个页面的请求时间,从而提高页面执行性能

我们的项目总是需要CSS和脚本文件。打包帮助你合并多个Javascript和css文件箌单个文件从而最小化多个请求到一个请求。

如果页面中有大量的javascript文件这样会降低性能。如果我们可以合并所有的JS文件到一个文件呮请求一个,这将加增加性能如下图所示:

MVC中如何执行打包?

在 BundleConfig.cs 中添加你想打包的JS文件路径到打包集合。如下所示:

一旦你合并了脚夲到一个文件你可以使用下面的专业代码是几位数去调用它:

你将看到脚本请求被合并到一个:

在debug模式下如何测试打包功能?

解释压缩它是如何执行的?

压缩功能通过移除空格、注释等减少了脚本与CSS文件的大小例如下面的专业代码是几位数:

执行压缩后的Javascript专业代码是幾位数如下所示。

}

??hi大家好,我是三合不知各位有没有想过,如果能把数据库操作和http访问都统一封装成接口(interface)的形式
然后接口对应的实现类由框架去自动生成,那么必然能大大降低笁作量因为不需要去写很多重复的专业代码是几位数了,还有一个好处是都是提供接口,我们把原来数据库操作的部分改成http访问,對于业务层来说是无感的,因为接口和方法都没变致力于降低上手net core的门槛,我开源了SummerBoot项目下面让我们来看一下效果。

数据库表对应實体类这些都是常规操作,略过

重头戏如何写接口,以一个简单的购物功能为例子

控制器中进行构造函数注入

 
 
??如果这篇文章对你囿所启发不妨点个赞吧



}

我要回帖

更多关于 专业代码是几位数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信