C#核心技术HelloWorld•//AHelloWorld!programinC#.•usingSystem;•namespaceHelloWorld•{•classHello•{•staticvoidMain()•{•Console.WriteLine(HelloWorld!);•//Keeptheconsolewindowopenindebugmode.•Console.WriteLine(Pressanykeytoexit.);•Console.ReadKey();•}•}•}Main方法Main方法是C#控制台应用程序或窗口应用程序的入口点。(库和服务不要求将Main方法作为入口点)应用程序启动时,Main方法是第一个调用的方法Main方法是驻留在类或结构内的static方法Main的返回类型有两种:void或int可以具有包含命令行实参的string[]形参,也可以不具有这样的形参注释①//AHelloWorld!programinC#.②/*AHelloWorld!programinC#.ThisprogramdisplaysthestringHelloWorld!onthescreen.*/C#程序的通用结构•//AskeletonofaC#program•usingSystem;•namespaceYourNamespace•{•classYourClass•{•}•structYourStruct•{•}•interfaceIYourInterface•{•}•delegateintYourDelegate();•enumYourEnum•{•}•namespaceYourNestedNamespace•{•structYourStruct•{•}•}•classYourMainClass•{•staticvoidMain(string[]args)•{•//Yourprogramstartshere...•}•}•}.NETFramework•.NET技术可以以规范和实现两部分来划分.•我们经常强调和提起的.NETFramework,主要包括公共语言运行时(CommonLanguageRuntime,CLR)和.NET框架类库(FrameworkClassLibrary,FCL),其实是对.NET规范的实现。•而另外一部分:规范,我们称之为公共语言架构(CommonLanguageInfrastructure,CLI),主要包括通用类型系统(CTS),公共语言规范(CommonLanguageSpecification,CLS)和通用中间语言(CommonIntermediateLanguage,CIL)。CLR•CLR(公共语言运行库,CommonLanguageRuntime)和Java虚拟机一样也是一个运行时环境,是一个可由多种编程语言使用的运行环境。•CLR的核心功能包括:内存管理、程序集加载、安全性、异常处理和线程同步,可由面向CLR的所有语言使用。并保证应用程序和底层操作系统之间必要的分离。•CLR是.NETFramework的主要执行引擎。.NETFramework版本•要知道是否已安装.NetFramework,只需检查%SystemRoot%System32目录中的MSCorEE.dll文件。存在该文件,表明.NetFramework已安装。•问题:•一台机器上可能安装了好几个版本,要了解安装了哪些版本,该如何检查呢?•这里提供一种常见而快捷的方法:•可检查以下注册表子项:•KEY_LOCAL_MACHINE/SOFTWARE/Microsoft/NETFrameworkSetup/NDP[Windows7Platform]内存管理•CLR管理内存的区域,主要有三块,分别为:•线程的堆栈,用于分配值类型实例。堆栈主要由操作系统管理,而不受垃圾收集器的控制,当值类型实例所在方法结束时,其存储单位自动释放。栈的执行效率高,但存储容量有限。•GC堆,用于分配小对象实例。如果引用类型对象的实例大小小于85000字节,实例将被分配在GC堆上,当有内存分配或者回收时,垃圾收集器可能会对GC堆进行压缩.•LOH(LargeObjectHeap)堆,用于分配大对象实例。如果引用类型对象的实例大小不小于85000字节时,该实例将被分配到LOH堆上,而LOH堆不会被压缩,而且只在完全GC回收时被回收。UsermyUser=newUser(){ID=100,Name=“TOM”};低地址高地址StackHeapmyUserObjectOtherObjectmyUser堆栈指针下一个对象实例低地址高地址GC•GC如其名,就是垃圾收集,当然这里仅就内存而言。•GarbageCollector(垃圾收集器,在不至于混淆的情况下也成为GC)以应用程序的root为基础,遍历应用程序在Heap上动态分配的所有对象,通过识别它们是否被引用来确定哪些对象是已经死亡的、哪些仍需要被使用。•已经不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收。•这就是GC工作的原理。•为了实现这个原理,GC有多种算法。比较常见的算法有ReferenceCounting,MarkSweep等等。•前主流的虚拟系统.NETCLR,JavaVM都是采用的MarkSweep算法。Mark-Compact•简单地把.NET的GC算法看作Mark-Compact算法。•阶段1:Mark-Sweep标记清除阶段,先假设heap中所有对象都可以回收,然后找出不能回收的对象,给这些对象打上标记,最后heap中没有打标记的对象都是可以被回收的;•阶段2:Compact压缩阶段,对象回收之后heap内存空间变得不连续,在heap中移动这些对象,使他们重新从heap基地址开始连续排列,类似于磁盘空间的碎片整理。•主要处理步骤:•将线程挂起→确定roots→创建reachableobjectsgraph→对象回收→heap压缩→指针修复。•可以这样理解roots:heap中对象的引用关系错综复杂,形成复杂的graph,roots是CLR在heap之外可以找到的各种入口点。•GC搜索roots的地方包括全局对象、静态变量、局部对象、函数调用参数、当前CPU寄存器中的对象指针等。•主要可以归为2种类型:①已经初始化了的静态变量②线程仍在使用的对象(stack+CPUregister)•Reachableobjects:指根据对象引用关系,从roots出发可以到达的对象。•例如当前执行函数的局部变量对象A是一个rootobject,他的成员变量引用了对象B,则B是一个reachableobject。•从roots出发可以创建reachableobjectsgraph,剩余对象即为unreachable,可以被回收。•指针修复是因为compact过程移动了heap对象,对象地址发生变化,需要修复所有引用指针,包括stack、CPUregister中的指针以及heap中其他对象的引用指针。GC小结•1、只管理内存,非托管资源,如文件句柄,GDI资源,数据库连接等还需要用户去管理。•2、循环引用,网状结构等的实现会变得简单。GC的标志-压缩算法能有效的检测这些关系,并将不再被引用的网状结构整体删除。•3、GC通过从程序的根对象开始遍历来检测一个对象是否可被其他对象访问,而不是用类似于COM中的引用计数方法。•4、GC在一个独立的线程中运行来删除不再被引用的内存。•5、GC每次运行时会压缩托管堆。•6、你必须对非托管资源的释放负责。可以通过在类型中定义Finalizer来保证资源得到释放。Finalizer的调用是在对象被标记为垃圾之后,GC回收对象之前的这个时间段里发生的。•7、对象的Finalizer被执行的时间是在对象不再被引用后的某个不确定的时间。注意并非和C++中一样在对象超出生命周期时立即执行析构函数.Finalizer的调用和GC的调用是运行在两个不同的线程里.•8、Finalizer的使用有性能上的代价。需要Finalization的对象不会立即被清除,而需要先执行Finalizer.Finalizer,不是在GC执行的线程被调用。•GC把每一个需要执行Finalizer的对象放到一个队列中去,然后启动另一个线程来执行所有这些Finalizer,而GC线程继续去删除其他待回收的对象。•在下一个GC周期,这些执行完Finalizer的对象的内存才会被回收。•9、.NETGC使用代(generations)的概念来优化性能。代帮助GC更迅速的识别那些最可能成为垃圾的对象。在上次执行完垃圾回收后新创建的对象为第0代对象。•经历了一次GC周期的对象为第1代对象。经历了两次或更多的GC周期的对象为第2代对象。•代的作用是为了区分局部变量和需要在应用程序生存周期中一直存活的对象。•大部分第0代对象是局部变量。成员变量和全局变量很快变成第1代对象并最终成为第2代对象。命名空间①.NETFramework使用命名空间来组织它的众多类.•System.Console.WriteLine(HelloWorld!);②在较大的编程项目中,声明自己的命名空间可以帮助控制类名称和方法名称的范围。使用namespace关键字可声明命名空间.•namespaceSampleNamespace•{•classSampleClass•{•publicvoidSampleMethod()•{•System.Console.WriteLine(•SampleMethodinsideSampleNamespace);•}•}•}类型•C#是一种强类型语言。•每个变量和常量都有一个类型,每个计算为值的表达式也是如此。•每个方法签名为每个输入参数和返回值指定一个类型。•.NETFramework类库定义了一组内置数值类型以及表示各种逻辑构造的更复杂的类型,例如文件系统、网络连接、对象的集合和数组及日期。•典型C#程序使用类库中的类型,还使用为特定程序问题域的概念建模的用户定义类型。类型中存储的信息①该类型的变量所需的存储空间。②该类型可以表示的最大值和最小值。③该类型包含的成员(方法、字段、事件等)。④该类型所继承的基类型。⑤将在运行时为其分配变量内存的位置。⑥允许的运算种类。示例•inta=5;•intb=a+2;//OK•booltest=true;•//Error.Operator'+'cannotbeappliedtooperandsoftype'int'and'bool'.•intc=a+test;在变量声明中指定类型•在程序中声明变量或常量时,必须指定其类型或者使用关键字var让编译器可以推断其类型。•下面的示例演示了一些使用内置数值类型和复杂的用户定义类型的变量声明:•//Declarationonly:•floattemperature;•stringname;•MyClassmyClass;•//Declarationwithinitializers(fourexamples):•charfirstLetter='C';•varlimit=3;•int[]source={0,1,2,3,4,5};•varquery=fromiteminsourcewhereitem=limitselectitem;练习1•如果有三个Bool型变量(a,b,c),写出程序片段可以推测出其中有2个以上变量的值是true?通用类型系统•.NETFramework中的类型系统的以下两个基本点:①它支持继承原则。类型可从称为基类型的其他类型派生。派生类型继承基类型的方法、属性和其他成员(存在一些限制),这种统一的类型层次结构称为常规类型系统(CTS)。②CTS中的每一个类型都被定义成了值类型或引用类型。使用关键字struct定义的类型是值类型;所有内置数值类型都是structs。使用关键字class定义的类型是引用类型。引用类型和值类型有不同