码迷,mamicode.com
首页 > Windows程序 > 详细

【CLR VIA C#】 笔记一

时间:2015-03-19 19:53:14      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:

 

工作几年了才看,记录下笔记备忘。

 

1.CLR的执行模型
  1. 公共语言运行时(Common Language Runtime,CLR)

  2. 源代码-->编译器检查语法和分析源代码-->托管模块(manged module)(含IL代码)-->运行时有JIT编译器生成cpu指令执行

  3. 托管模块由PE32|PE32+(64位)、CLR头、元数据、IL代码(中间语言运行时转换成CPU指令) 组成

  4. COM组件是一种规范,实现规范的DLL也可称为COM组件

  5. 托管模块中的元数据描述了模块中定义了什么以及引用了什么。

  6. 程序集:由托管模块、资源文件被编译器生成,包含一个mainfest清单的“组件”,可以是执行程序或DLL。

  7. 指定32位或anycpu时均可在64(64位系统中32位程序则在WOW64下执行)位下运行,可以在Environment的Is64BitOperatingSystem判断是否为64位操作系统

  8. IL是与CPU无关的机器语言,可视为面向对象的机器语言

  9. 有JITter(JIT编译器)(just in time)将IL即时编译成cpu指令(不同cpu生成对应指令),只有方法第一次执行时JIT编译器才会编译

  10. vs中生成-->高级-->调试信息 选择 full则可在vs中执行即时调试功能,选择none则不生成pdb文件,选择only则不共享生成代码,pdb位源码与IL的映射

  11. NGen.exe可以将IL代码提前编译成本机代码保存到磁盘文件中,避免运行时进行编译,但是没有做jit编译器所做的高度优化

  12. 将IL编译成CPU指令时,CLR执行验证(verification)过程,以检验程序的健壮性和安全性。

  13. 可以用unsafe关键字标记不安全的代码,CLR验证过程会跳过不安全代码。

  14. NGen.exe可提高程序启动速度,减少应用程序的工作集,缺点是没有防反编译、可能失去同步、代码未根据cpu优化

  15. Framework类库(Framework Class Library,FCL)

  16. WCF :Windows Communication Foundation

  17. 通用类型系统:Common Type System,CTS

  18. c#类只能单集成,接口可以多继承

  19. ==在引用情况下比较的是引用地址,equals一直比较值

  20. 公共语言规范:(Common Language Specification,CLS),实现通过com组件跨语言访问的规范,是CLR下各个编程语言的子集。可标记[assembly:CLSCompliant(true)]特性进行检查是否符合CLS。

2.生成、打包、部署和管理应用程序及类型
  1. 使用CSC.exe编译c#代码生成exe,可以通过 @响应文件名 来实现加载配置文件,默认全局CSC.rsp配置在.net文件夹下面

  2. 元数据包含:定义表、引用表、清单表

  3. 程序集特点:定义了可重用的类型、用一个版本号标记、可以关联安全信息。

  4. CLR只有在调用的方法确实引用了未加载程序集中的类型时,才会加载程序集。

  5. 程序集链接器:AL.EXE 可以实现生成包含不同编译器生成的模块,或者在生成时不清楚程序集的打包要求的模块,可以添加资源文件

  6. 程序集版本资源信息:在AssemblyInfo.cs中设置,可通过右键属性查看

  7. 版本号规则:使用4个句点分割:主版本号.次版本号.内部版本号(每天编译递增).修订号(每天编译次数递增)

  8. AssemblyFileVersion:给用户看的版本号 AssemblyInformationaVersion:调用此程序集的产品的版本号 AssemblyVersion:CLR检查的版本号

  9. 附属程序集:标记了语言文化的程序集,可用AL.exe生成

  10. 私有部署的程序集:在应用程序基目录或者子目录部署的程序集

  11. 指定程序集查找目录:在配置文件中增加probing 节点甚至privatePath路径,可以以分号分割,只能是子目录。winfrom为exe.config webfrom为web.config

  12. 机器.NET设置文件名为Machine.config在系统.net文件夹下面可找到

3.共享程序集和强命名程序集
  1. 弱命名程序集:普通程序集 强命名程序集:使用发布者的公钥、私钥进行签名,进行唯一性标识

  2. 弱命名可以私有部署、不能全局部署,强命名可以私有部署、可以全局部署

  3. 程序集唯一标识:文件名(无扩展名)、版本号、语言文化和公钥(公钥标记public key token)

  4. 使用SN.EXE创建公钥/私钥对,然后使用csc命令选择/keyfile 及类 来编译一个强命名程序集

  5. 全局程序集缓存(Global Assembly Cache,GAC):由多个应用程序访问的程序集存放的公认目录,一般在 系统/.net/assembly下,可以用GACUitl.exe进行程序集安装

  6. GAC只能安装强命名程序集,一般不推荐安装到GAC,如果安装则应该使用windows installer(MSI)进行安装

  7. CSX.EXE查找目录:1.工作目录 2.CSX所在目录,含CLR的各种DLL文件 3.使用/l编译器指定任何目录 4.使用LIB环境变量指定的任何目录

  8. 安装.net framework实际安装两套copy,一个安装在GAC(存在多个copy以便针对不同CPU优化),一个安装在CLR用于编译(不含IL代码,所以不依赖机器CPU)

  9. 强命名先使用私钥对程序集部分信息进行加密计算HASH,然后公钥写入程序集,最后再导入到GAC时用公钥解密结果与GAC计算结比较

  10. 如果从GAC之外加载强命名程序集,则CLR会在程序集加载后比较哈希值,保证每次程序集文件没有被篡改,GAC优先根据CPU类型搜索。

  11. 可以选择延迟签名,进行只放公钥及预留哈希存储空间,程序混淆的话必须用延迟签名才能澳证hash正确

  12. 配置文件的CODEBASE可以标记一个URL,CLR会自动下载文件,自动对比时间戳

  13. CLR解析类型引用:相同文件已经早期绑定直接加载,不同文件相同程序集,查找FILEDEF表,加载清单,不同文件不同程序集,加载被引用程序集的清单文件

  14. 配置文件可实现根据public key token、语言、版本号来替换一个DLL的功能

  15. 发布者策略控制:为程序集指定配置文件,指定更新版本
                           

4.类型基础
  1. 基类object包含MemberwiseClone(创建新实例)、Finalize(重写以实现垃圾回收前的操作)

  2. new一个对象时会计算所有类型直到object类型的成员所占的空间,然后传递参数后返回引用地址到对象

  3. is检查对象是否兼容于指定类型,as直接转换对象,两者好处位均不抛出异常,失败返回false和null。

  4. 引用类型重名时可以使用using a=system.IO;如果命名空间也重名则可用外部别名方式区分。

  5. CLR创建一个进程,进程可能有多个线程,线程创建时会分配到1MB的栈,按顺序执行,每个方法调用都会在调用栈中创建并压入一个栈帧,调用后释放栈帧。

  6. 堆上所有对象都包含:类型对象指针(GetType方法)和同步块索引,当CLR确认方法所需要的所有类型对象都已创建,方法的代码已经编译之后,就允许线程执行本机代码了。

  7. 栈中最简单的方法包含序幕(初始化为局部变量分配内存位null或0)和尾声(垃圾回收以便返回至调用者)

  8. 调用静态方法时CLR会定位与定义静态方法的类型对应的类型对象,然后JIT编译器在类型对象方法表中查找与被调用方法对应的记录项

  9. 调用非虚实例方法时JIT会找到与 发出调用的那个变量的类型 对应的类型对象,会向上找到基类,然后JIT查找方法表

  10. 虚方法调用先检查发出调用的变量,并更随地址来到发出调用的对象,然后检查“类型对象指针”成员,然后查找方法表
                           

5.基元类型、引用类型和值类型
  1. 基元类型:编译器直接支持的数据类型,和System.Int32是属于映射关系,如int、byte、float、double、decimal

  2. 不会发生数据丢失的情况下,c#允许隐式转换,使用关键字checked和unchecked可以检查是否溢出。

  3. 引用类型有托管堆分配,new后返回对象内存地址,值类型一般在线程栈上分配(会初始化0),类是引用类型,结构或枚举是值类型都继承自System.ValueType,引用类型传指针地址,值类型新建对象。

  4. 将值类型转换成引用类型就是装箱,在托管堆中分配内存(浪费资源),返回引用地址。将引用类型转换成值类型就是拆箱(只能转为原本值类型)。

  5. 检查同一性用ReferenceEquals,Equals默认实现同一性。

  6. dynamic在c#编译器生成payload(有效载荷),在运行时根据对象实际类型判断要执行什么操作。使用了称为运行绑定器得嘞。

6.类型和成员
  1. 类型默认访问性为internal,可以指定友元程序集来实现程序集访问限制。

  2. private、protected、internal、protected internal、public,派生类型重写后的可访问性要和重写成员具有相同可访问性。

  3. 静态类只能定义静态成员。

  4. partial关键字告诉c#编译器,类、结构、接口的定义源代码可能要分散到一个或多个源文件中。CLR对该功能一无所知,完全有编译器实现。

  5. 组件软件编程(Component Software Programming,CSP)

  6. call可调用静态方法、实例方法和虚方法,callvirt可调用实例方法和虚方法,不能调用静态方法,会检查对象是否为null,会递归查找调用对象。

  7. 应减少虚方法的使用,1是慢2是不能内嵌3版本控制脆弱4定义基类时要提供简单重载方法

  8. 应当对类使用sealed、internal关键字,对字段使用private关键字,然后考虑protected或internal最后考虑virtual。

  9. new关键字用在方法上时,是告诉编译器新方法和基类无任何关系,编译器将认为是此类上定义的新方法。override则是认为重写基类方法。
                           

7.常量和字段
  1. 常量const是值从不变化的符号,值会在编译时确定并保存为程序基元数据,基元类型均可定义为常量。常量值直接嵌入代码,不为常量分配内存。隐式为static。

  2. 静态字段实在第一次调用类是JIT编译时分配内存,实例字段则是在构造类型的实例时分配。readonly只能在构造函数里面赋值。

  3. readonly是运行时能赋值,常量则是一直固定的值。readonly不可改变的是引用,而非字段引用的对象。
                           

8.方法
  1. 引用类型:构造器是将类型的实例初始化为良好状态的特殊方法.ctor。创建引用类型时先为字段分配内存(默认为0或null),然后初始化附加字段类型对象指针和同步块索引,最后调用类的实例构造器来设置初始状态。

  2. 静态类不会生成默认构造器,是抽象密封类。构造器中不能调用虚方法。每个重载的构造器都会默认生成所有字段的值,所以通过this()调用其他构造器能减少IL代码量。

  3. 值类型:编译器不会生成和调用默认构造器,除非显式调用。字段总是被初始化为0或null。在值类型中this=new x();是允许赋值的,引用类型不行。new后再会将所有字段赋值为0;

  4. new是创建实例,并不是调用默认构造器。

  5. 使用static可以创建类型构造器,类型构造器永远没有参数,总是私有的,会在类型首次访问时执行。“.cctor”

  6. CLR规范要求操作符重载方法必须是public和static方法 如 operator+。

  7. 转换操作符试讲对象从一种类型转换成另一种类型的方法,必须是public和static方法。格式:方法加implicit operator 类名 是隐式转换,explicit operator 类名 是显式转换。

  8. c#扩展方法(第一个且只有第一个参数前有this),不支持扩展属性、事件等,必须在非反省的静态类中声明,类名没有限制,不能套在别的类,同时扩展了派生类。

  9. 分部类中可以声明分部方法,分部类是密封的,关键词partial.分部方法返回类型始终是void,且被视为private,并且参数不能有out。

9.参数
  1. 可为方法、构造器和有参属性指定默认值,有默认值的参数必须放在没有默认值的参数后面,默认值必须是编译时能确定的常量值。default和new都可以创建值类型实例。

  2. var不能用来声明方法的参数类型和声明类型中的字段,var只能声明方法内部的局部变量。

  3. 默认情况方法参数引用类型传指针,值类型传实例副本。ref和out区别在于由哪个方法负责初始化对象。传递引用方式给方法的变量类型必须与方法声明的参数类型相同。

  4. params关键字可实现可变数量的参数,只能为最后一个参数。 对性能有影响,可参考System.String的Concat方法设计。

  5. 声明方法的参数类型时,应指定最弱的类型,宁愿要接口也不要基类。如选IList而非List作为参数类型,方便扩展。一般最好将方法返回类型声明为最强类型。                       

10.属性
  1. 字段应设置为private,封装了字段访问的方法通常称为访问器。在属性中私有字段称为支持字段。声明属性而扛get、set方法的实现,c#会自动声明一个私有字段,自动实现的属性。

  2. 在任何想要序列化或反序列化的类型中,都不要用自动属性,因为每次生成的私有字段名称不固定。

  3. 属性不能作为out或ref参数,尽量减少属性使用。

【CLR VIA C#】 笔记一

标签:

原文地址:http://www.cnblogs.com/snnhoo/p/4351212.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!