1. 命名
System.Attribute 添加“Attribute”后缀;
System.Delegate 用于事件处理的委托,添加“EventHandler”后缀;
用于事件处理处的那些委托,添加“Callback”后缀;
System.EventArgs 添加“EventArgs”后缀;
System.Exception 添加“Exception”后缀;
Enum不要加前/后缀。
在程序集与名字空间、DLL中加入公司名字的前缀。
类,一般为名词或名词的词组,命名。如果你的类无法这样起名,那你可以考虑一下你的类的设计了。
方法,一般为动词或动词的词组。
属性,用名词、名词的词组或形容词,命名。布尔属性要加入”IS”、”CAN”、”HAS”等前缀。
事件,与方法差不多,可以加入时态作为后缀,不要加入Before,After等为前缀。当作为事件的委托时加入后缀“EventHandler”,参数一般用(Sender,e等)
参数,camelCasing风格,命名的意思要可读,不要使用类型。
资源,PascalCasing风格,其它与属性相似。
(P66 3-14 20:14电业局4楼)
1) 类与接口的选择
接口没有类灵活,一旦发布了,它的成员就永远固定了。类更灵活些,即使发布了也可以添加成员。(只要不是添加的抽象方法,如果是也要加上默认的实现。)任何已有的派生类无需改变仍能继续使用。
在C#中类只能单一继承,接口可以多继承。
Think:
如果想在一个已公开的接口中加入一些方法,为了不损坏子类中已继承了此接口的类,如何实现?
只能用一个新的接口去继承现有接口,在新接口中完成新方法的实现。
但是对于已实现老接口的类,想用到新的方法,就十分痛苦。会用到动态类型的转换,这样就会出现许多难以预知的异常。
e.g.
1.以发布的接口
publicinterface IStream {...}
publicclass FileStream : IStream {...}
2.在接口中加入新的方法
publicinterface ITimeoutEnableStream : IStream{
intReadTimeOut {get;set;}
}
publicclass FileStream : ITimeoutEnableStream{
publicint ReadTimeOut{ get{...} set{...} }
}
3.已有类中实现新方法(ReadTimeOut)
publicclass StreamReader{
publicStreamReader( IStream stream){ ... }
publicIStream BaseStream{ get{ ... } }
}
//---实现新功能---
StreamReaderreader =GetSomeReader();
ITimeoutEnableStreamstream = reader.BaseStream as ITimeoutEnableStream;
if (stream !=null ){ stream.ReadTimeOut = 100;
}//---繁琐、易错---
4.如果以前不是接口而是类,在基类中加入新的方法,实现就方便的多了
StreamReader reader = GetSomeReader ();
if( reader.BaseStream.CanTimeout){
reader.BaseStream.ReadTimeOut= 100;
}
JEFFERYRICHTER:
建议,先定义一个接口,然后定义一个实现该接口的抽象基类。用接口与对象进行交流,让最终的开发人员自己决定是基于你的抽象基数定义自己的类型(为了方便),还是基于他们想要的任何基类来定义自己的类型并实现该接口(为了灵活性)。
CHRISANDERSON:
如果你确实要定义2个对象间的协定,且协定不会随着时间而改变,那么接口非常合适。
如果要为一族类型定义一个公共基类,那么抽象基类会更好。
(P81 4-25 19:00电业局4楼)
什么时候用接口?
如果要提供一个多态的值类型层次结构的话,使用接口吧。
值类型不能自其它类型继承,但它可以实现接口。
考虑通过定义接口来达到与多重继承相类似的效果。
public struct Int32 : IComparable , IFormattable , IConvertible , IComparable<int> , IEquatable<int>
接口名以“er”结尾,最好。
接口最好只做一种功能的事情,否则你会后悔的。
JEFFREY RICHTER:当一个类派生自一个基类时,我说派生类与基类之间有IS-A关系。但是,当一个类实现一个接口时,我说实现接口的类与接口之间有CAN-DO关系。例,
public class FileStream : Stream
public abstract class Stream : MarshalByRefObject , IDisposable
public interface IDisposable
抽象类的设计
不要在抽象类型中定义仅有的构造函数。(抽象类本就不能实例,定义为公有的只能导致麻烦。)
BRAD ABRAMS:如果你自己没有定义构造函数的话,许多编程语言(如C#)会插入一个受保护的构造函数。在源代码中显式地定义构造函数是很好的做法,这样一来今后对源代码的归档和维护都会更容易。
静态类的设计
静态类被定义为一个只包含静态成员的类。它是密封的、抽象的,不能覆盖或声明任何实例成员。public static class File
静态类,尽量少用、目的一定要明确、不要声明或覆盖实例成员。
静态类相当于一个sealed abstract类,主要的一个优点是写在栈中,安全高速稳定,而且在执行的时候,十分优先。
类可以声明为 static 的,以指示它仅包含静态成员。不能使用 new关键字创建静态类的实例。静态类在加载包含该类的程序或命名空间时由 .NET Framework公共语言运行库 (CLR;特指:C#语言)自动加载。
Think:静态类与静态方法一样,不能实例化就可以使用。
JEFFREY RICHTER:结构静态是无用的,因为无论如何都能被实例化。只有类可以是静态的。
接口的设计
Think:一个类只能有一个基类(一般是名词如,人),但这个类可以有许多接口(一般是动词如,看、走、工作)。人只有一个父亲,但都可以看、走、工作。
要定义接口,如果你需要包括值类型在内的一组类型支持一些公共的API。
考虑定义接口,如果你需要让已自其它类型继承的类型支持该接口提供的功能。
要为你定义的每个接口提供至少一个使用该接口的API(一个以该接口为参数的方法,或是一个类型为该接口的属性。)
不要给已发行的接口再添加成员。
(P88 6-4 23:00出租屋内)