随笔 - 136  文章 - 0  评论 - 36  阅读 - 17万 
03 2011 档案
Microsoft.Net框架程序设计学习笔记(37):对象的代龄
摘要:利用对象代龄提高垃圾收集效率 代龄是旨在提高垃圾收集器性能的一种机制。一个基于代龄的垃圾收集器有以下几点假设:对象越新,其生存期越短。对象越老,其生存期越长。对托管堆的一部分执行垃圾收集要比对整个托管堆执行垃圾收集速度更快。 CLR将对象代龄分为0、1、2,共三代,且对每一代的对象所占用内存容量都设定了一个阀值,代龄越大,内存容量阀值也越大。代龄对象所占用内存超出阀值时,将引发垃圾收集。 在托管堆初始化时,其中不包括任何对象。这时添加到托管堆中的对象被称为第0代对象。当第0代对象所占用内存超过了阀值时,垃圾收集器就必须启动了。经过垃圾收集后存活下来的对象被认为是第1代对象,同时第0代对象暂时空 阅读全文
posted @ 2011-03-31 21:52 辛勤的代码工 阅读(343) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(36):弱引用
摘要:假设有这样一些数据结构,它们很容易创建但却需要大量的内存和时间。如:我们需要知道用户硬盘中所有目录和文件,我们可以很容易构造一个树来反映这些信息,当应用程序运行时,它可以引用内存中的树,而不必再访问用户的硬盘。这样显然会极大提高应用程序的性能。 但问题在于这个树可能会非常庞大,需要许多内存。如果用户转而访问应用程序的其余部分,那么这个树可能变得不再必要,却浪费着许多内存。我们可能会放弃这个树的根对象的引用,但如果用户又切换回应用程序的第一部分,那我们又需要重新构造该树。使用弱引用,我们可以方便、高效的处理这种情况。 弱引用对象是这样一种对象,如果我们放弃该对象的强引用,将其转至弱引用时,它允. 阅读全文
posted @ 2011-03-31 17:46 辛勤的代码工 阅读(271) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(35):Dispose模式
摘要:Finalize方法的问题:不能确定它会在何时被调用。由于它不是一个公有方法,我们不能显式调用它。 要提供显式释放或关闭对象的能力,一个类型通常要实现一种被称为Dispose的模式。所有定义了Finalize方法的类型都应该实现本节所描述的Dispose模式以给用户更多的控制权。 上节中OSHandle类实现的改进版,使用Dispose模式:using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;namespace DisposeTest{ pub. 阅读全文
posted @ 2011-03-31 16:59 辛勤的代码工 阅读(384) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(34):终止化操作
摘要:终止化操作 任何封装了非托管资源的类型,如文件、网络连接、套接字等,都必须支持一种称作终止化的操作。终止化操作允许一种资源在它所占用的内存被回收之前执行一些清理工作。要提供终止化操作,我们必须为类型重写一个名为Finalize的方法,该方法在Object中被定义为受保护的虚方法。当垃圾收集器判定一个对象为可收集的垃圾时,它便会调用该对象的Finalize方法。Finalize方法的实现通常便是调用CloseHandle函数。 然而,在C#中实现Finalize方法并非直接重写Finalize方法,C#编译器为我们提供了与C++析构函数类似特殊语法来定义Finalize方法。下例演示了如何定义一 阅读全文
posted @ 2011-03-30 23:20 辛勤的代码工 阅读(366) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(33):垃圾收集算法
摘要:每个.Net应用程序都有一组根(root)。一个根是一个存储位置,其中包含着一个指向引用类型的内存指针。该指针或指向一个托管堆中的对象,或被设为null。例如,所有的全局引用类型变量或静态引用类型变量都被认为是根。另外,一个线程堆栈上所有引用类型的本地变量或参数变量也被认为是一个根。最后,在一个方法内,指向引用类型对象的CPU寄存器也是一个根。 当JIT编译器编译一个方法的IL代码时,除了产生本地CPU代码外,JIT编译器还创建一个内部的表。该表中的每一个条目都标识着一个方法的本地CPU指令的字节偏移范围,以及该范围中一组包含根的内存地址(或CPU寄存器)。如下图: 如果在0x0000002. 阅读全文
posted @ 2011-03-30 21:30 辛勤的代码工 阅读(326) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(32):垃圾收集平台基本原理解析
摘要:创建、访问、释放资源的几个步骤:调用中间语言(IL)中的newobj指令,为表示某个特定资源的类型实例分配一定的内存空间。调用new操作符时,编译器产生newobj指令。初始化上一步所得的内存,设置资源的初始状态,使其可以为程序所用。类型实例构造器完成这类工作。通过访问类型成员来使用资源。销毁资源状态,执行清理工作。释放内存。引用类型所占的内存由垃圾收集器全权负责释放。值类型所占的内存将随着堆栈空间的消亡而自动消失,无所谓回收。 垃圾收集器对内存中的类型表示着何种资源一无所知,所以垃圾收集器并不清楚怎样执行上述步骤中的第4步。为使资源得到正确清理,开发人员必须自己编写这部分工作的代码。这些代码 阅读全文
posted @ 2011-03-30 20:43 辛勤的代码工 阅读(311) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(31):异常捕获、未处理异常、堆栈踪迹
摘要:异常捕获 异常捕获筛选器会判断抛出的异常类型是否和筛选器指定的类型相匹配,如果匹配成功,那么它会返回一个特殊的值通知CLR。CLR首先执行更低层次的堆栈中所有必要的finally块来清理其中启动的操作,展开调用堆栈。然后CLR才执行与抛出异常类型相匹配的catch块中的代码。未处理异常 登记AppDomain.CurrentDomain.UnhandledException事件可以处理当前应用程序域中的由托管代码抛出的未处理异常(不能处理非托管代码抛出的未处理异常)。该事件的委托原型为: public delegate void UnHandledExceptionEventHandler(o 阅读全文
posted @ 2011-03-30 13:48 辛勤的代码工 阅读(732) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(30):如何正确使用异常
摘要:类库开发人员使用异常的指导原则避免过多的finally块可以使用using语句来减少finally代码块。避免捕获所有异常如果我们设计的类型是一个类库的一部分,那么它绝对不应该捕获所有的异常(即捕获System.Exception),因为它不可能知道应用程序会如何处理这些异常。如果应用程序代码抛出了一个异常,应用程序的另一部分很可能期望能捕获该异常。这时我们应该让异常按照筛选器的筛选规则沿着调用堆栈向更高一层传递,直至找到能够处理它的应用程序代码。从异常中顺利的恢复我们捕获某个特定的异常时,应该完全理解导致抛出异常的情况,并清楚哪些异常类型继承自我们所捕获的异常。当异常无法修复时,回滚部分完成 阅读全文
posted @ 2011-03-30 11:30 辛勤的代码工 阅读(289) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(29):定义自己的异常类型与序列化类型
摘要:异常简介 C#只能抛出与CLS兼容的异常,即从System.Exception继承的异常类型。但CLR允许抛出任何类型的对象。C#为我们提供了一种特殊的catch块来捕获与CLS不兼容的异常: catch //这里没有指定异常筛选器{ //这里执行恢复代码 ....} 这样的catch块也可捕获任何与CLS兼容的异常。 finally块中的代码执行的是一些资源清理操作,这些清理操作通常是对应的try块中的行为所需要的。 异常是对程序接口隐含假设的一种违反。 在设计一个类型时,我们应该首先假设类型最常见的使用方式,然后设计其接口使之能够很好地处理这种情况。最后再考虑接口带来的隐含假设,并且当任何 阅读全文
posted @ 2011-03-30 10:50 辛勤的代码工 阅读(492) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(28):复制委托链上的委托对象、动态创建与调用委托
摘要:复制委托链上的委托对象 CLR默认的委托链调用处理在大多数情况下已经很好用了。但考虑一下以下的情况:希望获得委托链上每个回调方法的返回值?默认情况下我们只能获得最后一次调用的回调方法的返回值。被调用的委托中有一个抛出了异常。被调用的委托中有一个阻塞了很长时间。 由于委托链上的对象是按序调用的,所以如果有一个委托对象出了问题,将会阻止调用委托链上所有其他的委托对象。显然,这样的算法不够强健。 对于那些该算法不能满足的情况,MulticastDelegate类提供了一个实例方法GetInvocationList,我们可以使用它来显式调用委托链上的每一个委托对象。 该方法原型:public clas 阅读全文
posted @ 2011-03-29 22:49 辛勤的代码工 阅读(337) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(27):委托判等、委托链
摘要:委托判等 FCL中Delegate重写了Object的Equals虚方法,MulticastDelegate又重写了Delegate的Equals实现。MulticastDelegate重写的Equals方法在比较两个委托对象时会首先看它们的_target和_methodPtr字段是否都指向同样的对象和方法。如果这两个字段不匹配,那么返回false。如果这两个字段都匹配,那么再看两个委托对象是否为委托链表的头部(即_prec字段不为null)。如果两个委托对象的_prev字段指示的链表有相同的长度,且两个链表上对应委托对象的_target和_methodPtr字段也都互相匹配,那么Equals 阅读全文
posted @ 2011-03-29 22:09 辛勤的代码工 阅读(296) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(26):委托揭秘
摘要:让我们先看看以下示例代码:using System;using System.Collections.Generic;using System.Text;namespace DelegateTest{ //定义一个委托 public delegate void TestDelegate(int[] array); class Program { //定义一个数组,用于传递委托参数 static int[] array = new int[] { 1, 2, 3, 4, 5 }; //调用委托 static void Load(TestDelegate td) { if (td != null. 阅读全文
posted @ 2011-03-29 17:28 辛勤的代码工 阅读(355) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(25):检测定制特性、伪定制特性
摘要:检测定制特性 定义一个特性类型本身没有什么用处,应用程序代码的行为不会因此有任何改变。 在枚举类型上应用Flags特性可以改变System.Enum.ToString、Format方法的行为,这是因为它们会在运行时检测所操作的枚举类型上是否应用了Flags特性。应用程序利用反射技术来查找目标元素上应用了哪些特性。 如果我们是微软公司负责实现Enum类型中Format方法的员工,我们可能会像下面这样来实现它:public static String Format(Type enumType, Object value, String format){ //检测传入的枚举类型是否应用了Flags类 阅读全文
posted @ 2011-03-29 14:39 辛勤的代码工 阅读(305) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(24):定义自己的特性
摘要:自定义特性 假设我们是微软的员工,负责为枚举类型添加位标记支持。要实现这一点,我们首先定义一个FlagsAttribute类型: namespace System{ [AttributeUsage(AttributeTargets.Enum, Inherited = false)] public class FlagsAttribute : System.Attribute { public FlagsAttribute(){} }} 注意FlagsAttribute类型继承自System.Attribute,这使该特性成为一个与CLS兼容的定制特性。另外,所有的非抽象特性都必须具有publ. 阅读全文
posted @ 2011-03-29 12:26 辛勤的代码工 阅读(281) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(23):定制特性概述
摘要:定制特性仅仅是为目标元素提供关联附加信息的一种方式。编译器的工作只是将这些附加信息存放在托管模块的元数据中而已。大多数特性对编译器没有任何意义。编译器仅仅只是检测源代码中的定制特性,然后产生相应的元数据。 CLR允许将特性应用于任何可在一个文件的元数据中表示的元素(如:TypeDef、MethodDef、ParamDef、FieldDef、PropertyDef、EventDef、AssemblyDef、ModuleDef),也可以应该到元数据引用表中的条目上(如:AssemblyRef、ModuleRef、TypeRef、MemberRef),还可以应用到其他一些元数据中(如:安全许可、导. 阅读全文
posted @ 2011-03-29 11:38 辛勤的代码工 阅读(269) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(22):接口与完全限定接口名技巧
摘要:接口仅仅是一个包含着一组虚方法的抽象类型。 接口中也可以定义事件、无参属性、含参属性(即索引器),因为它们都不过是映射到方法上的语法缩写而已。 接口类型的名称要加一个大写的字母I前缀。接口定义允许使用修饰符--如public、protected、private、internal。 一个值类型可以实现一个或多个接口,但当我们将一个值类型实例转型为一个接口类型时,该值类型实例必须被执行装箱。因为接口总被认为是引用类型,且它们定义的方法总是虚方法。未装箱的值类型没有指向类型方法表的指针。 当我们创建可扩展的应用程序时,接口应该处于中心位置。假设我们正在编写一个应用程序,且希望其他人创建的类型能被我. 阅读全文
posted @ 2011-03-29 00:23 辛勤的代码工 阅读(544) 评论(2) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(21):数组的传递与返回、创建下限非0数组、快速访问数组
摘要:数组的传递与返回 如果我们定义了一个返回数组引用的方法,而在某些情况下数组又不含任何元素,那么我们的方法即可返回一个null,也可返回一个长度为0的数组引用。当我们实现这样的方法时,微软强烈建议我们让该方法返回一个0长的数组,因为这样会简化调用该方法的开发人员的编码工作。 同理,我们应该以同样的方式来处理字段。创建下限非0的数组 使用Array.CreateInstance静态方法可以动态创建下限非0的数组。 示例代码: 可使用Array.GetLowerBound和Array.GetUpperBound方法来获取此类数组的上下限索引号,以方便编码。快速访问数组 我们每次访问一个数组中的元素时 阅读全文
posted @ 2011-03-28 22:26 辛勤的代码工 阅读(322) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(20):数组Array基类介绍、数组转型
摘要:数组 所有的数组类型都隐含继承自System.Array,Array本身又继承自Object。 每个数组都有一些额外的负载信息,这些信息包括数组的维数、每一维的最低下限索引、每一维的长度、每一个元素的类型。 交错数组的定义示例: Point[][] myPolygons = new Point[2][]; myPolygons[0] = new Point[10]; myPolygons[1] = new Point[20]; 交错数组与CLS是不兼容的,CLS不允许一个数组的元素类型为Array,所以它不能在不同的编程语言中传递。数组基类Array Array实现了以下几个接口:ICl 阅读全文
posted @ 2011-03-28 21:53 辛勤的代码工 阅读(487) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(19):枚举类型与位标记
摘要:枚举类型 当编译一个枚举类型时,C#编译器会将其中的每个符号转变为类型的一个常数字段。 枚举类型就是一个定义了一组常数字段的结构而已。这些字段编译后会被存放在生成模块的元数据中,且可以通过反射来访问。 Enum的静态方法:static Type Enum.GetUnderLyingType(Type enumType)。该方法返回用于保存枚举类型实例值的基础类型。每个枚举类型都有一个基础类型,它们可以是byte、sbyte、short、ushort、int(C#选用的默认值)、uint、long或ulong。 我们可以在定义一个枚举类型的时候,让其中多个符号有着相同的数值。但当将一个数值转换为 阅读全文
posted @ 2011-03-28 14:36 辛勤的代码工 阅读(418) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(18):StringBuilder、字符串特定格式与语言文化、字符串编码与解码
摘要:StringBuilder 为了获得更高的性能,StringBuilder的方法并不保证线程安全。如果我们的程序需要对StringBuilder对象做多线程操作,那么我们必须显式添加线程同步代码。字符串特定格式与语言文化 如果我们希望自己的类型能为调用者提供格式和语言文化选择的话,我们就应该使其实现System.IFormattable接口: public interface IFormattable { String ToString(String format, IFormatProvider formatProvider); } format参数告诉方法应该怎样来格式化对象;format 阅读全文
posted @ 2011-03-28 11:42 辛勤的代码工 阅读(1152) 评论(0) 推荐(3) 编辑
Microsoft.Net框架程序设计学习笔记(17):字符串驻留
摘要:关于回车、换行 String s = "Hi\r\nthere."; 以上代码将回车、换行字符硬编码到字符串中,但更加好的做法是使用System.Enviroment类型提供的一个名为NewLine的只读属性。 示例代码: String s = "Hi" + Enviroment.NewLine + "there."; 这样做的好处是,NewLine属性依赖于特定平台,根据底层平台的不同,它的返回值也不同。在Windows系统上运行时,该属性返回的字符串为"\r\n"。如果将CLR移植到UNIX系统上,NewLin 阅读全文
posted @ 2011-03-28 00:59 辛勤的代码工 阅读(405) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(16):显式控制事件注册
摘要:有时我们会感到编译器自动产生的add和remove方法不够理想。如:我们需要频繁地添加或移除委托实例,同时我们又知道我们的程序是在单线程环境下运行,这时再对包含委托实例的对象进行同步访问的话就会损伤应用程序性能。 C#编译器允许我们显式实现add和remove访问器方法。示例代码如下:public class MailManager{ public delegate void MailMsgEventHandler(Object sender, MailMsgEventArgs args); //显式定义一个私有委托链表字段 private MailMsgEventHandler mailM. 阅读全文
posted @ 2011-03-27 21:59 辛勤的代码工 阅读(292) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(15):事件之原理分析
摘要:完整定义一个事件的方法 以Mail发送为例:定义一个类型用于保存所有需要发送给事件通知接受者的附加信息。按.Net框架约定,所有保存事件信息的类型都应该继承自System.EventArgs,且类型的名称应该EventArgs结束。 public class MailMsgEventArgs : EventArgs { public readonly string from, to, subject, body; public MailMsgEventArgs(string from, string to, string subject, string body) { this.from = 阅读全文
posted @ 2011-03-27 21:39 辛勤的代码工 阅读(334) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(14):属性
摘要:当定义一个属性时,编译器会在生成的托管模块中产生以下3项:一个表示属性的get访问器的方法。只有为属性定义了get访问器方法时,才有这一项。一个表示属性的set访问器的方法。只有为属性定义了set访问器方法时,才有这一项。一个位于托管模块元数据中的属性定义,不管是只读、只写、或读写属性都有这一项。 阅读全文
posted @ 2011-03-27 15:51 辛勤的代码工 阅读(303) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(13):虚方法调用机理
摘要:CLR提供了两个IL指令来调用方法:call和callvirt。 call指令根据引用变量的类型来调用一个方法。 callvirt指令根据引用变量指向的对象类型来调用一个方法。 当编译源代码时,编译器知道代码中是否在调用一个虚方法,并据此产生call或callvirt指令。产生call而不是callvirt会提高代码的性能,因为CLR不必检查引用对象的实际类型。 不管最终是通过call还是callvirt来调用一个实例方法,所有的实例方法调用都会接受一个隐藏的this指针作为方法的第一个参数,其中this指针指向当前正在操作的对象。 阅读全文
posted @ 2011-03-27 15:23 辛勤的代码工 阅读(302) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(12):操作符重载、转换操作符、引用参数、可变数目参数
摘要:操作符重载方法: CLR对操作符重载一无所知,它甚至都不认识操作符是什么。我们选择的编译语言定义了每个操作符的含义,以及当遇到它们时产生什么样的代码。 如在C#中,应用于基元数值类型上的+符号会使编译器产生将两个数相加的代码。 虽然CLR对操作符一无所知,但它却规范了编程语言应该怎样提供操作符重载。对于CLR来讲,重载操作符仅仅是一些方法而已。 以下代码:class Complex{ public static Complex operator+(Complex c1, Complex c2) {......}} 编译器会产生一个名为op_Addition的方法定义,该方法定义条目上有一个sp 阅读全文
posted @ 2011-03-27 15:14 辛勤的代码工 阅读(350) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(11):类型构造器
摘要:除实例构造器外,CLR还支持类型构造器(又称静态构造器、类构造器、类型初始化器)。类型构造器用于设置一个类型的初始状态。默认情况下,一个类型中没有定义类型构造器,只能手动定义。且类型构造器不能有任何参数。 示例代码如下:class SomeRefType{ //当SomeRefType第一次被访问时执行 static SomeRefType() {}}struct SomeValType{ //当SomeValType第一次被访问时执行 static SomeValType() {}} 类型构造器不允许添加任何访问限制符,它的访问限制被自动设为私有方式。类型构造器的调用由CLR负责,CLR会. 阅读全文
posted @ 2011-03-27 12:24 辛勤的代码工 阅读(281) 评论(0) 推荐(0) 编辑
通过序列化实现深拷贝
摘要:关于浅拷贝和深拷贝,我的理解不是很清晰,简单说来,我认为是这样子: 浅拷贝:引用成员在被拷贝时仅复制源对象中引用成员的地址到新对象中,所以在新对象中对引用成员进行更改会影响到源对象(除对引用成员进行赋值外)。 深拷贝:引用成员在拷贝时新建一个引用对象到新对象中,且将源对象中引用对象的成员值复制到新对象的引用对象中,所以在新对象中对引用成员进行更改不会影响源对象。 说起来概念也简单,我想大家纠结的是如何实现深拷贝?浅拷贝的实现很简单,调用Object.MemberwiseClone就万事大吉了。在网上找了一个通过序列化实现深拷贝的例子,自己改了改,欢迎大家品头论足。 这段程序的输出为: obj. 阅读全文
posted @ 2011-03-26 00:26 辛勤的代码工 阅读(789) 评论(1) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(10):实例构造器
摘要:创建一个引用类型的实例时,系统分以下三步骤:首先为该实例分配内存。初始化对象的附加成员(即方法表指针和一个SyncBlockIndex)调用类型的实例构造器设置对象的初始状态。 以下情况,类型实例的创建不需要调用实例构造器。调用Object的MemberwiseClone方法,它将执行以下几步:为对象分配内存,初始化对象的附加成员,将源对象的字节拷贝到新创建的对象中。反序列化一个对象时,通常也不会调用构造器。 内联方式初始化实例字段的语法,如下:class ClassA{ int i = 5;} 实际上内联方式初始化实例字段的简化语法都被转换成了构造器中的代码。这时,如果在构造器中又对字段进. 阅读全文
posted @ 2011-03-26 00:16 辛勤的代码工 阅读(281) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(9):常数与只读字段
摘要:常数是在编译时嵌入代码中,所以常数在运行时不再需要任何内存分配。我们不能获取常数的地址,或以引用的方式来传递一个常数。 如果要求一个模块中的数值能够在运行时而非编译时被另一个模块获取,那就不应该使用常数,因为常数在编译时就已经被嵌入到程序的IL代码中了。这时,应该使用只读字段。 只读字段只能在构造器内被赋值,且在构造器内只读字段可以多次被赋值。 对于静态只读字段只能在静态构造器内赋值,静态构造器在该类型初次被引用时执行。 阅读全文
posted @ 2011-03-25 23:11 辛勤的代码工 阅读(317) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(8):对象散列码、对象克隆
摘要:对象的散列码: object提供了一个GetHashCode虚方法,我们可以从任何对象上得到一个Int32类型的散列码。 如果我们定义了一个类型,且重写了Equals方法,我们就应该重写GetHashCode方法。因为Hashtable类型的实现要求任何两个相等的对象都必须有相同的散列值。 object的GetHashCode方法返回的是一个在应用程序域范围内确保唯一的数值,该数值在对象的整个生存期中保证不会改变。但在对象被执行垃圾收集后,这个唯一的数值可以被重新利用作为一个新的对象的散列码。 ValueType中实现的GetHashCode方法使用反射来返回定义在类型中第一个实例字段的散列码 阅读全文
posted @ 2011-03-25 18:11 辛勤的代码工 阅读(486) 评论(2) 推荐(1) 编辑
Microsoft.Net框架程序设计学习笔记(7):重写Object.Equals方法
摘要:System.Object类型提供了名为Equals的虚方法,目的为判断两个对象是否有相同的“值”。.Net框架类库(FCL)中许多方法在内部都调用了Equals方法(如:Array的IndexOf方法、ArrayList的Contains方法)。对于没有显式重写Equals的类型,Object(或重写了Equals方法的最近的那基类)提供的实现将被继承。以下代码展示了System.Object类型中的Equals方法实现: class object { public virtual Boolean Equals(object obj) { //如果引用指向的是同一对象,肯定相等 if (t. 阅读全文
posted @ 2011-03-25 17:23 辛勤的代码工 阅读(515) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(6):算术运算溢出处理checked与unchecked操作
摘要:考虑以下代码:byte b = 100;b = (byte)(b+200); 这段代码在实际运行中是否会抛出溢出异常呢? 先不管答案,我们来看看CLR是如何应对溢出的: CLR提供的IL指令允许编译器选择自己期望的行为。CLR提供了一个名为add的指令,会直接对两个数做加法运算,而不做任何溢出检查。同时,CLR还提供了一个名为add.ovf的指令,它在对两数做加法运算时,一旦发出溢出,便会抛出一个System.OverflowException异常。除这两个加法运算指令外,CLR还提供了类似的减法(sub/sub.ovf)、乘法(mul/mul.ovf),以及数据转换(conv/conv.o. 阅读全文
posted @ 2011-03-25 12:56 辛勤的代码工 阅读(604) 评论(1) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(5):延迟签名
摘要:延迟签名的作用: 当我们打包强命名程序时,必须使用安全的私有密钥来为之签名。然而在开发和测试程序集时,允许访问安全的私有密钥可能会导致私钥泄漏。为在开发与测试环境中保证私钥安全,.Net推出了延迟签名技术,也叫局部签名。延迟签名的步骤:开发程序集时,首先取得仅包含公司公有密钥的文件,并将以下两个特性加入到AssemblyInfo.cs文件中://指定公有密钥文件名[assembly:AssemblyKeyFile("MyCompany.Publickey")]//指定延迟签名特性为true[assembly:AssemblyDelaySign("true" 阅读全文
posted @ 2011-03-25 10:48 辛勤的代码工 阅读(340) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(4):部署强命名程序集到全局程序集缓存(GAC)
摘要:如果一个程序集被多个应用程序所访问,为方便起见,应该将其放到一个CLR确知的目录下,这个目录即全局程序集缓存(GAC)。 全局程序集缓存所在路径一般为:c:\Windows\Assembly 向GAC中安装一个强命名程序集的常用工具为:GACUtil.exe 使用方法: 安装一个强命名程序集到GAC中 GACUtil /i xxx.dll 从GAC中删除一个强命名程序集 GACUtil /u xxx.dll GACUtil一般不会和客户应用程序一起发布,如果应用程序包括一些需要部署到GAC中的程序集,则必须的使用2.0版本以上的Windows安装器(MSI)。客户电脑上一般总是存在该工具。可. 阅读全文
posted @ 2011-03-25 10:47 辛勤的代码工 阅读(376) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(3):强命名程序集的创建
摘要:强命名程序集的创建使用SN(Strong Name Utility)工具创建密钥例:SN -k MyCompany.keys创建一个名为MyCompany.keys的密钥文件,该文件包含一对以二进制格式存储的公有密钥和私有密钥。查看公有密钥方法创建一个只含有公有密钥的文件SN -p MyCompany.keys MyCompany.Publickey查看公有密钥SN -tp MyCompany.Publickey显示如下:Microsoft (R) .NET Framework 强名称实用工具 版本 2.0.50727.42Copyright (c) Microsoft Corporation 阅读全文
posted @ 2011-03-25 10:46 辛勤的代码工 阅读(398) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(2):弱命名程序集与强命名程序集的区别
摘要:弱命名程序集与强命名程序集的区别:程序集部署:弱命名程序集只能进行私有部署,即只能部署在应用程序的基目录及子目录下;强命名程序集既可进行私有部署,也可进行全局部署。程序集定位:弱命名程序集可以在其清单元数据中嵌入版本号和语言文化特性,但CLR总会忽略版本号,仅利用程序集的名称进行定位,只有在搜寻子目录查找卫星程序集时才会使用其中的语言文化信息。强命名程序集包含4个唯一标识程序集的特性:文件名(不含扩展名)、版本号、语言文化标识、一个公有密钥标记(由公有密钥产生的一个值)。在定位时,唯有这4个特性完全匹配才能定位成功。 阅读全文
posted @ 2011-03-25 10:45 辛勤的代码工 阅读(384) 评论(0) 推荐(0) 编辑
Microsoft.Net框架程序设计学习笔记(1):程序集文件的定位
摘要:当CLR要定位一个程序集时,它将扫描应用程序的几个子目录,下面是CLR扫描一个语言文化中性的程序集时的顺序: AppBase\AsmName.dll AppBase\AsmName\AsmName.dll 如果在上面的目录下没有找到该程序集,CLR将以.exe代替.dll扩展名来搜索。如果仍找不到,将抛出FileNotFoundException异常。 对于其他语言文化程序集(即卫星程序集)来说,除了期望被放在应用程序集目录下,且名字和语言文化相匹配的子目录外,其他规则仍适用。 以"en-US"为例,CLR将扫描以下目录: AppBase\en-US\AsmName.dll 阅读全文
posted @ 2011-03-25 10:44 辛勤的代码工 阅读(410) 评论(0) 推荐(0) 编辑
C#多线程编程之:Timer(定时器)使用示例
摘要:Timer类:设置一个定时器,定时执行用户指定的函数。定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数。构造函数:Timer(TimerCallback callback, object state, int dueTime, int period)参数说明 callback:一个 System.Threading.TimerCallback 委托,表示要执行的方法。 state:一个包含回调方法要使用的信息的对象,或者为 null。 dueTime:调用 callback 之前延迟的时间量(以毫秒为单位)。指定 System.Threading.Timeout.Infinite 阅读全文
posted @ 2011-03-25 10:43 辛勤的代码工 阅读(7368) 评论(0) 推荐(0) 编辑
C#多线程编程之:同步事件和等待句柄
摘要:同步事件和等待句柄用于解决复杂的同步情况。比如一个大的计算步骤包含3个步骤result = first term + second term + third term,如果现在想写个多线程程序,同时计算first term,second term 和third term,等所有3个步骤计算好后再把它们汇总起来,我们就需要使用到同步事件和等待句柄。 同步事件分有两个,分别为AutoResetEvent和ManualResetEvent,这两个类可以用来代表某个线程的运行状态:终止和非终止。 等待句柄用来判断ResetEvent的状态,如果是非终止状态就一直等待,否则放行,让等待句柄下面的代码继. 阅读全文
posted @ 2011-03-25 10:41 辛勤的代码工 阅读(1508) 评论(1) 推荐(0) 编辑
C#多线程编程之:Monitor使用示例及Mutex简介
摘要:Monitor类功效和lock类似: 1 System.Object obj = (System.Object)x; 2 System.Threading.Monitor.Enter(obj); 3 try 4 { 5 DoSomething(); 6 } 7 finally 8 { 9 System.Threading.Monitor.Exit(obj);10 } lock关键字比Monitor简洁,其实lock就是对Monitor的Enter和Exit的一个封装。 另外,Monitor还有几个常用的方法: (1) TryEnter TryEnter能够有效的决绝长期死等的问题,如果在一个并 阅读全文
posted @ 2011-03-25 10:39 辛勤的代码工 阅读(1508) 评论(0) 推荐(0) 编辑
C#多线程编程之:集合类中Synchronized方法与SyncRoot属性原理分析(转)
摘要:我们知道,在.net的一些集合类型中,譬如Hashtable和ArrayList,都有Synchronized静态方法和SyncRoot属性,他们之间有联系吗?我怎么才能用好他们呢? 以Hashtable为例,看看他们的基本用法:1 Hashtable ht = Hashtable.Synchronized(new Hashtable());2 lock (ht.SyncRoot)3 {4 ......5 } Synchronized表示返回一个线程安全的Hashtable,什么样的 hashtable才是一个线程安全的呢?下边我们就从.NET的源码开始理解。1 public static . 阅读全文
posted @ 2011-03-25 10:27 辛勤的代码工 阅读(9414) 评论(2) 推荐(0) 编辑
C#多线程编程之:lock使用注意事项
摘要:1.避免锁定public类型对象。 如果实例可以被公共访问,将出现lock(this)问题。 如有一个类MyClass,该类有一个Method方法通过lock(this)来实现互斥: 1 public class MyClass 2 { 3 public void Method() 4 { 5 lock(this) 6 { 7 ...... 8 } 9 }10 } 如果一个MyClass的实例在不同线程中执行Method方法,可以实现互斥。但如果多个MyClass的实例分别在不同的线程中执行Method方法,互斥将失效,因为此处的lock(this)仅对当前的实例对象进行了加锁。2.禁止锁定类 阅读全文
posted @ 2011-03-25 10:25 辛勤的代码工 阅读(2475) 评论(5) 推荐(4) 编辑

点击右上角即可分享
微信分享提示