C#语言基础原理及优缺点
C# 是专门为 .net 程序框架而创造的语言。
.net 框架有 ms 的 .netFramework, Mono 的 .NetFramework ( 也是符合 .net IL 语言, CTS 规范, CLS 规范 , CLR 运行时库 ) , mono 程序可以运行在各种操作系统和游戏平台中运行(目前 mono 还不够成熟影响力较小 ) 。
.net 原理主要是编译的原理 : IL 中间语言 , CLR 运行时环境。
.net 程序组成体系主要概念:应用程序集,应用程序域。
.net程序编译过程:
1)编译时:.netvs或mono编译器(或其它编译器)将 源代码 (C#,VB,托管C++,J#,JScript,调用的底层C/C++代码COM) 编译为 编译器 定义的 中间语言 IL 。
2) 运行时: CLR (.net或mono实现的)把 IL 语言用 JIT (按需即时编译)为平台上专用的 机器代码 ,把JIT编译好的机器代码存储起来,下次运行这部分代码时候就不用编译了。
所以需要把.net运行库(CLR一整套代码)安装到需要运行.net 程序的机器中才能运行程序。
.net中的语言都是符合.net规范的,比如 强类型,单继承,分号等比较大致的规定,语言本身细节没有太多苛刻要求。
.net程序编译和执行过程中的流程图:
一、优点及原理:
1. 强大的.Net Framework托管代码集合类, 封装了大多数windows上使用的技术组件类, 文件系统,UI界面,数据源访问,网络访问,COM互操作(图形图像多媒体,WPF图形系统),没有的可以通过.net的平台调用win API函数来得到。
2. 较简单的语言特性:自动内存管理, 单继承,支持事件、委托、属性、Linq等一系列让业务开发更简单的功能。
3. Web应用程序开发非常快(.net框架的支持,控件可以拖拉(UI方便编辑和定位),添加事件(跳转到控制逻辑层),ADO.net数据源访问, xml 网络类库, windows服务)。
Web窗体:System.Web.UI.WebControls.WebControl类。
XML Web服务,客户端请求,服务端返回xml 而不是html 的.net页面。
Window服务:System.ServiceProcess命名空间中的.net基类,可以支持很多window服务先关的事情。
桌面应用开发,window窗体:System.Windows.Forms.Control,.net 3.0中中的WPF。
4. 和语言平台无关的编译机制,及较快的运行速度( ms 不推荐 , mono 的 Xamarin, Unity 还不错 ) :编译成 IL 中间语言 , CLR公共语言运行库托管代码 ,CLR根据运行时程序需要将IL中间语言用JIT即时编译方式编译为内部机器代码,对编译好的机器代码缓存起来,提高了程序速度。
.net中的所有托管语言都是使用这样的编译机制,即javascript在.net中是编译型的,而不是解释型编译的。托管的C++可以调用非托管的C++,但.net中对C++有限制不能使用模板或类的多继承,且要启用指针还需要对项目指定为CLR内存类型是非安全的。.net组合了COM的互操作性,因此托管代码可以调用COM组件,COM组件也可以调用托管代码。
平台无关:ms .net用IL和CLR理论可以做到但是实际不能跨平台的,mono是跨平台的.net 实现但影响力较小。
语言之间交互:
COM: COM是基于二进制通信的,调用方(客户程序)可以用COM运行库实例化需要的COM对象,然后通过COM对象指针来调用需要的方法或属性。组件和组件之间只通过COM运行库来通信(相互实例化)有局限(不过耦合度更底),COM不允许客户程序继承实现COM类,COM对不同的语言只能单独的调试。
IL和CLR:利用.net编译器,编译为统一的中间代码(CLR规范), 比二进制更高一层,使得语言之间的交互更加灵活。
不同语言的类可以继承 ( 继承 ) ,一个语言可以包含另一个语言的实例 ( 关联组合聚合 ) , 对象可以在方法之间传递 ( 依赖 ) , 可以相互处理异常的抛出 ( 定义了统一的.net 类来表示异常 ) ,可以调试不同语言编写的源代码。
IL中间语言规范:
中间语言的主要特性:面向对象和使用接口,值类型和引用类型间巨大差别,强数据类型,使用异常类来统一处理各语言中的异常,使用特性。
中间语言的这些规范的好处:
语言互操作,垃圾回收,安全性,应用程序域的实现 。
语言互操作:
数据存储的规范:引用类型总是存储在托管堆的内存区域中,值类型一般存储在栈中。
数据类型规范:强数据类型,必须明确一个变量或常量的类型,不能使用variant, 指针在标记了的C#中(非内存安全)或托管C++(非内存安全)中可以使用。
CTS(通用类型系统): 所有托管语言定义的类型,都会编译为中间语言定义的通用类型;VB中整型,C#中的int 都会被编译映射为int32, 这样不同的语言通过CTS就可以相互继承,关联组合,依赖实现通信。类型分为值类型和引用类型,值类型(内置,枚举,用户定义的值类型),引用(接口,指针,自我描述), 自我描述(数组,类), 类(用户定义的类,委托,装箱值类型)。
CLS(公共语言规范): CLS是一个最低语言规范标准集,例如CLS指定不使用任何只是根据大小写区分的名称(不区分大小写的语法),以前的VB代码就可以和CLS兼容代码一起使用,可以定制编译选项(支持部分的CLR特性的编译器编写,语言之间的相互通信)。
垃圾回收器(GC):COM是用引用计数,AddRef计数加1,Release计数减1且到0时候释放内存(还是需要手动的Release内存)。.net中是采用垃圾回收器,当.net运行库CLR检测到给定进程的托管堆已满,需要清理时,就调用垃圾回收器,检查所有托管堆中对象的引用,对引用为0的对象则清理内存。
注意:在引用环中长期持有会导致内存占用泄露,例如放置到全局或静态容器中的对象,数据库或网络链接中的对象池等。
CLR垃圾回收器调用是不确定的,所以对于内存开销比较大的程序逻辑,需要手动在代码中调用垃圾回收器。
C#中也可以显示的调用析构函数,可以方便的释放内存资源。
代码安全性:window是基于角色的安全机制,.net提供了基于代码的安全机制,由于中间语言提供了类型安全性,CLR在运行前检查代码,确定是否有需要的安全权限, CLR没有权限则不能执行该代码。
5. 更好的程序组件结构,应用程序域和程序集:
应用程序域是指进程空间中的内存区域作为一个应用程序域,用于组件及应用程序之间的安全快速的 通信 。
程序集
应用程序域(进程空间中):原来window应用程序组件DLL是通过加载在同一进程中(4GB的内存空间及安全标识,一个组件出错会影响到其它组件,导致崩溃),或者exe间是通过进程间复制数据实现通信的(内存共享机制,也会带来性能上的损失)。
.net CLR引入了应用程序域,希望可以解决这样的问题。一个进程空间内可以有多个应用程序域,一个应用程序域大致对应一个应用程序,执行的线程都对应一个具体的应用程序域。
这样理论上将需要通信的应用程序加入到相同进程中的一个应用程序域中,那么进程空间中的应用程序就可以直接的访问彼此的数据,但是有中间语言的类型安全机制(C#不建议使用指针,CLR会对数组边界进行安全检查保证不越界),所以除非明确使用不安全的特性,否则不能进行通信。但可以通过.net远程服务来快速的在安全或不安全特性的应用程序间相互通信或共享数据。
而对于不同组件间通信,可以将组件划分到不同的应用程序域中,一个大的应用程序就由多个应用程序域组成。这样组件之间既可以快速的通信且不会导致一个组件出错,会影响整个系统的崩溃。
程序集(磁盘组件中): 原来是.lib,.dll库组件,exe运行程序的程序体系结构,.net中使用了程序集概念。程序集是为了解决以前 COM 组件注册麻烦 , COM 组件信息获取麻烦 (需要从注册表中获取组件的GUID和接口, 属性和方法也需要从类库中获取),可能组件数据信息不同步问题 (共享数据被塞满,dll被其它同名dll覆盖)。
程序集(assembly)是包含编译好的,面向.net CLR的代码逻辑单元,描述了程序集中所有类型,和这些类型的成员细节。
用 文件集 的方式解决注册麻烦(直接存放),用 程序集清单和元数据 解决组件信息获取麻烦问题,及 加载程序集时候用程序集入口文件描述 了其它文件的细节、散列、内容,避免文件被替换或塞满,依然加载程序集,导致数据分散后不同步的问题。
一个程序集可以存储在多个文件中(动态程序集存储在内存中),如果一个程序集存储在多个文件中,其中有一个包含入口点的主文件,该文件描述了程序集中的其它文件细节、散列和内容,如果一个文件被替换或被塞满,系统肯定会检测出来,并拒绝加载程序集。
程序集分为: 可执行程序集和库程序集 ,它们使用相同的程序集结构,只是可执行的程序集包含了一个主程序入口点。也可以程序是否运行分为 静态程序集,动态程序集 ,静态程序集存储在磁盘文件中,动态程序集存储在内存中。类型分为: 共享程序集和私有程序集 。
私有程序集:只有单一的应用程序可以使用,.net程序集默认是私有程序集,安装非常简单, 只需要把相应的文件放在文件系统中对应的文件夹中即可 (不需要注册表项)。私有程序集不能被其它程序使用,因为应用程序只能加载位于主执行文件所在文件夹或其子文件夹中的程序集。
共享程序集:其它的应用程序也可以使用的公共库,需要能够实现快速共享,需要防止程序集命名冲突,程序集不同版本的相互覆盖。
共享:共享程序集需要特殊的处理,需要用.net工具来完成,将共享程序集放置在全局程序集高速缓存(GAC)中建立一个小的文件夹层次结构并对共享程序集进行检查。
命名冲突:共享程序集应根据私有密钥加密法指定一个名称(私有程序集只需要指定一个和主文件名相同的名字即可),它必须由引用共享程序集的程序来引用。
版本覆盖:可以在程序集清单中指定版本信息来解决,也可以通过同时安装来解决。
其它:
特性:在程序中提供某些项相关的信息,供编译器使用。.net提供了机制。在文栋说明书中十分有用,可和反射技术一起使用,根据特性执行编程任务。使得一种语言中定义,另一种语言中可以读取。
反射:利用程序集描述的类型和类型成员详细信息,可在运行期获取特性的详细信息,或者作为实例化类、调用方法的一种间接的方式,如果把方法上的类名指定为字符串(类名为参数),就可以选择类来实例化方法,以便在运行时调用,而不是编译时调用。
64bit支持,泛型和迭代器,匿名方法,部分类,可空类型。
二、缺点:
1. 底层和高性能不合适: 不合适做 时间性能很高 (高速算法) 或空间性能很灵活 (内存立即释放)的程序,因为中间语言和编译过程,比C/C++Native类型的语言会慢一些,内存自动回收难以立即释放不需要的内存,不采用内联函数和析构函数(不建议)。
2.Windows平台以外支持有限:Java,Python等是很强大的。
三、总结:
C#更像是一门胶水和强大应用层语言(底层都是C/C++, WINAPI, COM 的OLE VB, DirectX, 或者mono项目上定制的库); 且 .net 基于 IL 的 CLR 运行时库,和应用程序集,应用程序域却是一个对应用程序编译和应用程序组成体系比较大的创新 ; 但优点同时也会带来缺点,底层或实时高性能应用程序方面难以代替C/C++,windows平台以外的应用开发还需要不断的进步(Xamarin, Unity做得还不错), 故也不能替代java,oc,python,lua等众前辈或后生。总之语言都是工具而已(高手更在于人,而不在于剑, 在什么场合拿上最合适的剑即可,或军刀或长矛)。
- QQ群
-
微信
- 返回首页
- 返回顶部