1、用属性代替可访问的字段算法
一、.NET数据绑定只支持数据绑定,使用属性能够得到数据绑定的好处;编程
二、在属性的get和set访问器重可以使用lock添加多线程的支持。数组
一、const只可用于基元类型、枚举、字符串,而readonly则能够是任何的类型;安全
二、const在编译时将替换成具体的常量,这样若是在引用中同时使用了const和readonly两种值,则对readonly的再次改变将会改变设计的初衷,这是须要从新编译所更改的程序集,以从新引用新的常量值。服务器
三、const比readonly效率高,但失去了应用的灵活性。多线程
一、二者都是在运行时进行类型的转换,as操做符只能使用在引用类型,而is可使用值和引用类型;框架
二、一般的作法是用is判断类型,而后选择使用as或强类型转换操做符(用operater定义的转换)有选择地进行。ide
一、ConditionalAttribute只用于方法级,对其余的如类型、属性等的添加都是无效的;而#if #endif则不受此限制;函数
二、ConditionalAttribute能够添加多个编译条件的或(OR)操做,而#if #endif则能够添加与(AND)[这里能够彻底定义为另外一个单独的符号];工具
三、ConditioanlAttribute定义能够放在一个单独的方法中,使得程序更为灵活。
一、能够更友好的方式提供用户详细的信息;
二、使用IFormatter.ToString()方法提供更灵活的定制,若是添加IFormatProvider 和ICustomFormatter接口则更有意义的定制消息输出。
一、值类型不支持多态,适合存储应用程序操做的数据,而引用则支持多态,适用于定义应用程序的行为;
二、对于数组定义为值类型能够显著提升程序的性能;
三、值类型具备较少的堆内存碎片、内存垃圾和间接访问时间,其在方法中的返回是以复制的方式进行,避免暴露内部结构到外界;
四、值类型应用在以下的场景中:类型的职责主要是用于数据存储;公共接口彻底由一些数据成员存取属性定义;永远没有子类;永远没有多态行为。
一、使咱们的代码更易于编写和维护;
二、初始化常量的三种策略:在构造中;工厂方法;构造一个可变的辅助类(如StringBuilder)。
一、值类型的默认状态应为0;
二、枚举类型的0不该为无效的状态;在FlagsAttribute是应确保0值为有效地状态;
三、在字符串为为空时能够返回一个string.Empty的空字符串;
一、ReferenceEquals()判断引用相等,须要两个是引用同一个对象时方可返回true;
二、静态的Equals()方法先进性引用判断再进行值类型判断的;
三、对于引用类型的判断能够在使用值语义时使用重写Equals()方法;
四、重写Equals()方法时也应当重写GetHashCode()方法,同时提供operater==()操做。
一、GetHashCode()仅应用在基于散列的集合定义键的散列值,如HashTable或Dictionary;
二、GetHashCode()应当遵循相应的三条规则:两个相等对象应当返回相同的散列码;应当是一个实例不变式;散列函数应该在全部的整数中产生一个随机的分布;
一、foreach能够消除编译器对for循环对数组边界的检查;
二、foreach的循环变量是只读的,且存在一个显式的转换,在集合对象的对象类型不正确时抛出异常;
三、foreach使用的集合须要有:具有公有的GetEnumberator()方法;显式实现了IEnumberable接口;实现了IEnumerator接口;
四、foreach能够带来资源管理的好处,由于若是编译器能够肯定IDisposable接口时可使用优化的try…finally块;
一、字段生命默认会将值类型初始化为0,引用类型初始化为null;
二、对同一个对象进行屡次初始化会下降代码的执行效率;
三、将字段的初始化放到构造器中有利于进行异常处理。
一、静态构造器会在一个类的任何方法、变量或者属性访问以前执行;
二、静态字段一样会在静态构造器以前运行,同时静态构造器有利于异常处理。
一、用this将初始化工做交给另外一个构造器,用base调用基类的构造器;
二、类型实例的操做顺序是:将全部的静态字段都设置为0;执行静态字段初始化器;执行基类的静态构造器;执行当前类型的静态构造器;
将全部的实例字段设置为0;执行实例字段初始化器;执行合适的基类实例构造器;执行当前类型的实例构造器。
在IDisposable接口的Dispose()方法中用GC.SuppressFinalize()可通知垃圾收集器再也不执行终结操做。
一、分配和销毁一个对上的对象都要花费额外的处理器时间;
二、减小分配对象数量的技巧:常用的局部变量提高为字段;提供一个类,用于存储Singleton对象来表达特定类型的经常使用实例。
三、用StringBuilder进行复杂的字符串操做。
一、关注一个类型到System.Object的隐式转换,同时值类型不该该被替换为System.Object类型;
二、使用接口而不是使用类型能够避免装箱,即将值类型从接口实现,而后经过接口调用成员。
一、使用非内存资源,它必须有一个终结器,垃圾收集器在完成没有终结其的内存对象后会将实现了终结器对象的添加到终结队列中,而后垃圾收集器会启动一个新的线程来运行这些对象上的终结器,这种防护性的变成方式是由于若是用户忘记了调用Dispose()方法,垃圾回收器老是会调用终结器方法的,这样能够避免出现非托管的内存资源不被释放引发内存泄漏的问题;
二、使用IDisposable.Dispose()方法须要作四个方面的工做:释放全部的非托管资源;释放全部的托管资源;设置一个状态标记来表示是否已经执行了Dispose();调用GC.SuppressFinalize(this)取消对象的终结操做;
三、为须要多态的类型添加一个受保护的虚方法Dispose(),派生类经过重写这个方法来释放本身的任务;
四、在须要IDisoposable接口的类型中,即便咱们不须要一个终结器也应该实现一个终结器。
一、不相关的类型能够共同实现一个共同的接口,并且实现接口比继承更容易;
二、接口比较稳定,他将一组功能封装在一个接口中,做为其余类型的实现合同,而基类则能够随着时间的推移进行扩展。
一、在基类中实现一个接口时,派生类须要使用new来隐藏对基类方法的使用;
二、能够将基类接口的方法申明为虚方法,而后再派生类中实现。
一、委托对象自己不提供任何异常捕获,因此任何的多播委托调用都会结束整个调用链;
二、经过显示调用委托链上的每一个委托目标能够避免多播委托仅返回最后一个委托的输出。
一、应当声明为共有的事件,让编译器为咱们建立add和renmove方法;
二、使用System.ComponentModel.EventHandlerList容器来存储各个事件处理器,在类型中包含大量事件时可使用他来隐藏全部事件的复杂性。
一、因为值类型对象的访问会建立一个该对象的副本,因此定义一个值类型的的属性彻底不会改变类型对象内部的状态;
二、常量类型能够避免改变对象的状态;
三、定义接口将访问限制在一个子集中从而最小化对对象内部状态的破坏;
四、定义一个包装器对象来限制另外一个对象的访问;
五、但愿客户代码更改内部数据元素时能够实现Observer模式,以使对象能够对更改进行校验或相应。
能够避免在多个相似的手工编写的算法中犯错误的可能性,并提供清晰和可读的代码。
一、类型表示的不是UI控件、窗口或者表单,都应使类型支持序列化;
二、在添加了NonSerializedAttribute的反序列化的属性时能够经过实现IDeserializationCallback的OnDeserialization()方法装入默认值;
三、在版本控制中可使用ISerializable接口来进行灵活的控制,同时提供一个序列化的构造器来根据流中的数据初始化对象,在实现时还要求SerializationFormatter异常的许可。
四、若是须要建立派生类则须要提供一个挂钩方法供派生类使用。
一、IComparable接口用于为类型实现最天然的排序关系,重载四个比较操做符,能够提供一个重载版的CompareTo()方法,让其接受具体类型做为参数;
二、IComparer用于提供有别于IComparable的排序关系,或者为咱们提供类型自己说没有实现的排序关系。
一、对于值类型永远不须要支持ICloneable接口使用默认的赋值操做便可;
二、对于可能须要支持ICloneable接口的基类,应该为其创造一个受保护的复制构造器,并应当避免支持IConeable接口。
经过使用构造器来代替转换操做符可使转换工做变得更清晰,因为在转换后使用的临时对象,容易致使一些诡异的BUG。
一、建立一个兼容的程序集须要遵循两条规则:程序集中全部公有和受保护成员所使用的参数和返回值类型都必须与CLS兼容;任何与CLS不兼容的公有和受保护成员都必须有一个与CLS兼容的替代品;
二、能够经过显式实现接口来避开CLS兼容类型检查,及CLSCompliantAttribute不会检查私有的成员的CLS兼容性。
一、JIT编译器以方法为单位进行编译,没有被调用的方法不会被JIT编译;
二、若是将较长的Switch中的Case语句的代码替换成一个一个的方法,则JIT编译器所节省的时间将成倍增长;
三、短小精悍的方法并选择较少的局部变量能够得到优化的寄存器使用;
四、方法内的控制分支越少,JIT编译器越容易将变量放入寄存器。
一、将全部的公有类以及共用的基类放到一些程序集中,把为公有类提供功能的工具类也放入一样的程序集中,把相关的公有接口打包到他们本身的程序集中,最后处理遍及应用程序中水平位置的类;
二、原则上建立两种组件:一种为小而聚合、具备某项特定功能的程序集,另外一种为大而宽、包含共用功能的程序集。
一、使用接口来暴露类型的功能,可使咱们更方便地建立内部类,同时又不会限制他们在程序集外的可用性;
二、向外暴露的公有类型越少,将来扩展和更改实现所拥有的选择就越多。
这是在机器之间的交易的频率和载荷都降到最低,将大的操做和细粒度的执行放到服务器执行。
一、一个事件处理器抛出异常,则事件链上的其余处理器将不会被调用,而重写的虚方法则不会出现这种状况;
二、重写要比关联事件处理器高效得多,事件处理器须要迭代整个请求列表,这样占用了更多的CPU时间;
三、事件能在运行时响应,具备更多的灵活性,能够对同一个事件关联多个响应;
四、通行的规则是处理一个派生类的事件是,重写方式较好。
一、System.Diagnostics.DebugTraceEventLog为运行时提供了程序添加诊断信息所须要的全部工具,EventLog提供入口时的应用程序能写到系统事件日志中;
二、最后不要写本身的诊断库,.NET FCL 已经拥有了咱们须要的核心库。
一、.NET框架的System.Windows.Application类为咱们定义了创建通用配置路径的属性;
二、Application.LocalAppDataPath和Application.userDataPath 会生成本地数据目录和用户数据的路径名;
三、不要在ProgramFiles和Windows系统目录中写入数据,这些位置须要更高的安全权限,不要期望用户拥有写入的权限。
一、BindingMananger和CurrencyManager这两个对象实现了控件和数据源之间的数据传输;
二、数据绑定的优点:使用数据绑定要比编写本身的代码简单得多;应该将它用于文本数据项以外的范围-其余显示属性也能够被绑定;对于Windowos Forms 数据绑定可以处理多个控件同步的检查相关数据源;
三、在对象不支持所需的属性时能够经过屏蔽当前的对象而后添加一个想要的对象来支持数据绑定。
一、ASP.NET中有五种控件来验证有效性,能够用CustomValidator派生一个新类来增长本身的认证器;
二、Windows验证须要子System.Windows.Forms.Control.Validating些一个事件处理器。
一、数组有两个比较明显的缺陷:不能动态的调整大小;调整大小很是耗时;
二、ArrayList混合了一维数组和链表的特征,Queue和Stack是创建在Array基础上的特殊数组;
三、当程序更加灵活的添加和删除项时,可使更加健壮的集合类型,当建立一个模拟集合的类时,应当为其实现索引器和IEnumberable接口。
一、DataSet有两个缺点个:使用XML序列化机制的DataSet与非.NET 代码之间的交互不是很好;DataSet是一个很是通用的容器;
二、强类型的DataSet打破了更多的设计规则,其得到的开发效率要远远高于本身编写的看上去更为优雅的设计。
经过设计和实现特性类,强制开发人员用他们来声明可被动态使用的类型、方法和属性,能够减小应用程序的运行时错误,提升软件的用户满意度。
一、Invoke成员使用的参数和返回值都是System.Object,在运行时进行类型的转换,但出现问题的可能性也变得更多了;
二、接口使咱们能够获得一个更为清晰、也更具可维护性的系统,反射式一个很强大的晚期绑定机制.NET框架使用它来实现Windows控件和Web控件的数据绑定。
一、须要不一样的异常类的惟一缘由是让用户在编写catch处理器时可以方便地对不一样的错误采起不一样的作法;
二、可能有不一样的修复行为时咱们才应该建立多种不一样的异常类,经过提供异常基类所支持的全部构造器,能够为应用程序建立功能完整的异常类,使用InnerException属性能够保存更低级别错误条件所产生的全部错误信息。
一、强异常保证在从异常中恢复和简化异常处理之间提供了最好的平衡,在操做由于异常而中断,程序的状态保留不变;
二、对将要修改的数据作防护性的复制,对这些数据的防护性复制进行修改,这中间的操做可能会引起异常,将临时的副本和原对象进行交换;
三、终结器、Dispose()方法和委托对象所绑定的目标方法在任何状况下都应当确保他们不会抛出异常。
一、互操做有三个方面的代价:数据在托管堆和非托管堆之间的列举成本,托管代码和非托管代码之间切换的成本,对开发人员来讲与混合环境打交道的开发工做;
二、在interop中使用blittable类型能够有效地在托管和非托管环境中来回复制,而不受对象内部结构的影响;
三、使用In/Out特性来确保最贴切的没必要要的屡次复制,经过声明数据如何被列举来提升性能;
四、使用COM Interop用最简单的方式实现和COM组件的互操做,使用P/Invoke调用Win32 API,或者使用C++编译器的/CLR开关来混合托管和非托管的代码;
一、尽量的避免访问非托管内存,隔离存储不能防止来自托管代码和受信用户的访问;
二、程序集在Web上运行时能够考虑使用隔离存储,当某些算法确实须要更高的安全许可时,应该将那些代码隔离在一个单独的程序集中。
一、使用NUnit创建自动单元测试(集成在VS2010 中了);
二、FXCop工具会获取程序集中的IL代码,并将其与异族编码规则和最佳实践对照分析,最后报告违例状况;
三、ILDasm是一个IL反汇编工具,能够帮助咱们洞察细节;
四、Shared Source CLI是一个包含.NET框架内核和C#编译器的实现源码。
1.foreach VS for 语句
Foreach 要比for具备更好的执行效率Foreach的平均花费时间只有for的30%.经过测试结果在for和foreach均可以使用的状况下,咱们推荐使用效率更高的foreach另外,用for写入数据时间大约是读取数据时间的10倍左右.
2.避免使用ArrayList
ArrayList的性能低下任何对象添加到ArrayList中都要封箱为System.Object,从ArrayList中取出数据都要拆箱回实际的类型 泛型集合类的高性能,泛型集合是强类型的
3.使用HashTable字典集合
当存放少许数据时建议使用HashTable取代像StringDictionary,NameValueCollection, HybridCollection这样的字典集合
4.为字符串容器声明常量
为字符串容器声明常量,不要直接把字符串封装在双引号””中,避免字符串对象不断在内存中建立和释放.提升字符串对象的访问效率.
//避免MyObject obj = new MyObject();obj.Status = “Active”;
//推荐const string c = “Acive”;MyObject obj = new MyObject();obj.Status = c;
5.使用String.Compare()字符串比较不要使用UpperCase或LowerCase转换字符串的大小写,再进行比较使用String.Compare()可忽略字符串大小写进行比较
String strTemp = “Active”;If(String.Compare(strTemp,”active”,true)==0){ Consolt.Write(“Equal”);}
6.使用StringBuilder字符串拼接1.String类对象是不可变的(只读),
对于String对象的从新赋值,本质是从新建立一个新的String对象并赋予新值给该对象.2.System.Text.StringBuilder 维护一个长度等于Capacity的字符串(能够看做字符数组),当Capacity长度的字符串不足以容纳结果字符串时,StringBuilder开辟新的长度为通过上面的规则计算好的Capacity的内存区域,将原字符串复制到新的内存区域再进行操做,原字符串区域交给GC回收。所以这里也涉及到内存的分配与回收,使用StringBuilder时最好估算一下所需容量,用这个容量初始化Capacity,提升性能。StringBuilder不能保证全部实例成员都是线程安全的,尽管在类型定义中加入了不少线程安全的控制,若是要确保其线程安全,须手工实现线程同步机制。
7.XPathDocument读取XML文件若是只是读取XML对象的数据,那么用只读的XPathDocument代替XMLDocument,能够提升性能
8.避免在循环体里声明变量,
应该在循环体外声明变量,在循环体内初始化变量
//避免For(int i=0;i<10;i++){ SomeClass obj = new SomeClass(); //…}
//推荐SomeClass obj = null;For(int i=0; i<10; i++){ obj = new SomeClass(); //…}
9.捕获指定的异常捕获异常时,
应使用具体的异常类进行捕获,并按照异常所捕得到范围按照由小到大的顺序进行定义不要使用通用的
System.ExceptionPrivate void Find(object obj){
try{
Console.write(obj.ToString());
}
catch(ArgumentNullException ane)
{ //… }
catch(ArgumentException ae)
{ //… }
catch(SystemException se)
{ //… } catch(Exception e)
{ //… } }不要使用Exception控制流程,捕获异常对性能的损耗是众所周知的.所以最好可以避免异常的发生
10.使用using和try/finally清理资源.NET 平台在内存管理方面提供了GC(Garbage Collection),
负责自动释放托管资源和内存回收的工做,但它没法对非托管资源进行释放,这时咱们必须本身提供方法来释放对象内分配的非托管资源使用非托管资源的类型必须实现IDisposable接口的Dispose方法来精确的释放资料当使用带有Dispose方法的类型化资源时,应在使用完毕时调用Dispose方法,及时释放掉不用的资源.使用using或try/finally能更好的保证Dispose方法被及时的调用
11.避免滥用反射反射是比较浪费性能的操做,
应避免滥用反射影响性能的缘由:当使用反射来调用类型或触发方法,访问字段属性时,CLR须要作更多的工做:校验参数,检查权限等.当编写一个动态构造类型(晚绑定)的应用时,可采起如下方式进行替换经过类的继承关系经过接口实现经过委托实现
12.避免装箱操做使用值类型的ToString方法避免装箱操做缘由:
数字和字符串拼接的时候,由于数据类型不一样,数字经过装箱操做转换为引用类型后才能与字符串进行拼接.
//建议int num=5;string str = “link me”+num.ToString();
13.HttpServerUtility.Transfer 采用 Server.Transfer 语法,
在页面中使用该方法可避免没必要要的客户端重定向(Response.Redirect)。
Int32.TryParse()类型转化Int32.TryParse()优于Int32.Parse()优于Convert.ToInt32()
Convert.ToInt32 会把最终的解析工做代理给Int32.Parse
Int32.Parse 会把最终的解析工做代理给Number.ParseInt32
Int32.TryParse 会把最终的解析工做代理给Number.TryParseInt32