.如果可能尽量使用接口来编程
NET框架包括类和接口在编写程序的时候你可能知道正在用NET的哪个类然而在这种情况下如果你用NET支持的接口而不是它的类来编程时代码会变得更加稳定可用性会更高请分析下面的代码
private void LoadList (object [] items ListBox l)
{
for (int i = ; i < itemsLength;i++)
lItemsAdd (items[i]ToString ());
}这个函数从一个可为任何对象的数组中加载ListBox这段代码被限定为只能使用数组假想过些时候你发现那些对象存在数据库中或别的集合中那么你 需要修改程序来使用不同的集合类型如果你用ICollection接口来写那段程序你就不用修改那段程序了对于任何实现ICollection接口 的类型它都能很好的工作:
private void LoadList (ICollection itemsListBox l)
{
foreach (object o in items)
lItemsAdd (oToString ());
}
ICollection被数组和所有SystemCollection中的集合实现此外多维数组也支持ICollection接口如果那还不够的话数据库NET类同样支持ICollection接口用接口写的这个函数不用需改就可以才许多中情况下使用
使用属性代替原始数据
因为属性已经成为语言本身的元素所以声明数据元素时它的作用域等级没有必要大于private因为代码本身会把属性看成数据元素你并没有失去使用 简单数据类型的便利性 相反它会使你的代码更加灵活功能更加强大属性使你的数据元素封装性更好属性可以让你使用lazy evaluation来返回数据lazy evaluation的意思是当用户请求时才计算它的值而不是一直保留着它
最后属性可以是virtual也可以是abstract你也可以在接口中定义属性
这里还有维护方面的因素应当注意尽管操作两者的方法是一样的但是你把一个数据元素变成属性那么原先客户端的程序便不能访问服务端的新版本程序了实际上对于在Web service中你想实现序列化的值你可以把它们变成属性来使用
private int TheMonth = ;
[XmlAttribute (Month)]
public int Month
{
get {
return TheMonth;
}
set {
TheMonth = value;
}
}
简单通过属性就可以使你的所有数据元素私有化
在Producer/Consumer 的Idiom中使用Delegate
当你生成一个实现producer idiom类的时候使用deletate来通知consumer这种方法相对于用接口更加灵活Delegate是多点传送的所以不用加额外的代码你就何以支持多用户相对于用接口这样做可使类之间的耦合性降低
下面的类处理键盘输入并把它传给所有的registered listeners
public class KeyboardProcessor
{
private OnGetLine theFunc = null;
public OnGetLine OnGetLineCallback {
get {
return theFunc;
}
set {
theFunc = value;
}
}
public void Run (){
// Read input
// If there is any listeners publish:
string s;
do {
s = ConsoleReadLine ();
if (sLength == )
break;
if (theFunc != null){
SystemDelegate [] funcs =theFuncGetInvocationList();
foreach (OnGetLine f in funcs) {
try {
f (s);
} catch (Exception e) {
ConsoleWriteLine
(Caught Exception: {} eMessage);
}
}
}
} while (true);
}
任何数目的listeners都可注册到producer它们所要做的只是提供一个特定的函数deletate
注意初始化顺序
C#中对于一些变量声明加入了initializer的概念它们在构造函数之前被执行实际上变量在基类的构造函数执行前之前被初始化
所以在初始化变量的时候不要用基类中的数据因为它们还没有被构造