首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

第7章 施用规范

2012-12-21 
第7章 使用规范7.1.?数组ü?要在公用API中优先使用集合,而不是优先使用数组。???不要使用只读的数组字段。pub

第7章 使用规范

7.1.?数组

ü?要在公用API中优先使用集合,而不是优先使用数组。

?

??不要使用只读的数组字段。

public?static?readonly?char[] chars = {?'<',?'>',?'='?};//bad

?

ü?考虑使用不规则数组,而不要使用多维数组。

//good

int[][] jaggedArray={

new?int[]{1,2,3},

new?int[]{1,2,3,4,5},

new?int[]{8}

};

?

//bad

int[,] multiDimArray={

{1,2,3,4},

{2,3,4,5},

{4,0,0,0}

};

?

7.2.?Attribute

ü?要在命名自定义attribute类时添加“Attribute”后缀。

?

ü?要在定义自己的attribute时使用AttributeUsageAttribute。

?

ü?要为可选参数提供可设置的属性。

?

ü?要为必填参数提供只读属性。

?

ü?要提供构造函数参数来对鼻涕 参数进行初始化。

?

??避免提供构造函数参数来对与可选参数对应的属性进行初始化。

?

??避免对自定义attribute的构造函数进行重载。

?

ü?要尽可能将自定义attribute类密封起来。这样会使查找attribute更快。

[AttributeUsage(

AttributeTargets.Class |?AttributeTargets.Method,

AllowMultiple =?true, Inherited =?false)]

public?class?LastModifiedAttribute?:?Attribute

{

private?readonly?DateTime?dateModified;

private?readonly?string?changes;

private?string?issues;

?

public?LastModifiedAttribute(string?dateModified,?string?changes)

{

this.dateModified =?DateTime.Parse(dateModified);

this.changes = changes;

}

?

public?DateTime?DateModified

{

get?{?return?dateModified; }

}

public?string?Changes

{

get?{?return?changes; }

}

public?string?Issues

{

get?{?return?issues; }

set?{ issues =?value; }

}

}

7.3.?集合

??不要在公用API中使用弱类型集合。

?

??不要在公用API中使用ArrayList或List<T>。当客户代码修改时无法收到消息。如Add()方法

?

??不要在公用API中使用Hashtable或Dictionary<TKey,TValue>。

?

??不要使用IEnumerator<T>、IEnumerator或实现了这两个接口之一的任何其他类型,除非是作为GetEnumerator方法的返回值。

?

??不要在同一个类型中同时实现IEnumerator<T>和IEnumerable<T>。对非泛型接口IEnumerator和Enumerable来说也同样如此。类型要么是集合,要么是枚举器,不能两者都是。

7.3.1.?集合参数

ü?要用最泛的类型来作为参数类型。大多数的集合为参数的成员都使用IEnumerable<T>接口。

public?void?PrintNames(IEnumerable<string> names)

{

foreach(string?name?in?names)

Console.WriteLine("name:{0}",name);

}

?

??避免使用ICollection<T>或ICollecton来做参数。

ICollection<T> :?IEnumerable<T>,?IEnumerable

ICollection?:?IEnumerable

7.3.2.?集合属性与返回值

??不要提供可设置的集合属性。

public?Collection<Persons> Persons{get{...},set{...};}//bad

?

ü?要用Collection<T>或其子类作为属性或返回值来表示可读写的集合。

public?Collection<string> Legs

{

get;

}

?

ü?要用ReadOnlyCollection<T>或其子类作为属性或返回值来表示只读的集合。

public?ReadOnlyCollection<string> Eyes

{

get{return?new?ReadOnlyCollection<string>(eyes);}

}

?

ü?考虑使用泛型集合基类的子类,而不要直接使用该集合。

public?class?CowCollection:Collection<Cow>{...}

?

ü?要用Collection<T>或ReadOnlyCollecton<T>的子类来作为常用方法和常用属性的返回值。

?

ü?如果集合中存储的元素都有独一无二的键值,考虑使用有键集合(keyed collection),。

?

??不要从集合属性或以集合为返回值的方法中返回null,替代方法是返回一个空集合或空数组。

?

??不要让属性返回“snap collection”,属性应该返回“live collection”。表示某个时间点的状态的集合称为“snapshot Collection”,如数据库的查询。始终表示当前状态的集合称为live collection。

?

ü?要用snapshot collection或live IEnumerable<T>来表示不稳定的集合。

7.3.3.?自定义集合的实现

??不要继承自非泛型的集合基类,比如CollectionBase,要使用Collection<T>。实际上,很多情况下,我们都不会从CollectionBase中派生类。知道内部的工作原理是好事,因为List<T>以相同的方式工作,但CollectionBase是向后兼容的。使用CollectionBase的唯一场合是要更多的控制向类的的用户展示的成员。如果希望集合类的Add()方法使用内部访问修饰符,则使用CollectionBase是最佳选择。

?

ü?要为强类型的非泛型集合实现IEnumerable<T>。如果合理,还可以考虑实现ICollection<T>甚至IList<T>。

?

??如果类型的API很复杂,而且与集合的概念无关,避免为类型实现集合接口。

?

ü?要在为实现了IEnumerable的类型命名是添加“Collection”后缀。

?

ü?要在为实现了IDictionary或IDictionary<TKey,TValue>的类型命名是添加“Dictionary”后缀。

?

??避免给集合抽象的名字添加代表其具体实现的后缀,比如“LinkedList”或“Hashtable”。

?

ü?考虑用集合元素的类型名作为集合名字的前缀。

?

ü?考虑给只读集合的名字添加“ReadOnly”前缀。

7.3.4.?数组与集合之间的选择

ü?要优先使用集合,而不是优先使用数组。

?

ü?考虑在底层API中使用数组,以降低内存的消耗并提高性能。

?

ü?要使用字节数组,而不要使用字节集合。

public?Collection<byte> ReadBytes(){...}//bad

public?byte[] ReadBytes(){...}//good

?

??不要将数组用于属性。

7.4.?ICloneable

??不要实现ICloneable。

?

??不要在公用API中使用ICloneable.

?

ü?考虑为需要克隆机制的类型定义Clone方法。一定要在文档中明确说明该方法是深复制还是浅复制。

7.5.?Icomparable<T>与IEquatable<T>

ü?要为值类型实现IEquatable<T>。主要从性能考虑,object.Equals会导致装箱操作。

?

ü?要在实现IEquatable<T>.Equals时,同样遵循为覆盖Object.Equals而制定的规范。

?

ü?要在实现IEquatable<T>的同时覆盖Object.Equals。

?

ü?考虑在实现IEquatable<T>的同时重载“operator ==” 和“Operator !=”。

?

ü?要在实现IComparable<T>的同时实现IEquatable<T>。

?

ü?考虑在实现IComparable<T>的同时重载比较操作符(<、>、<=、>=)。

7.6.?IDisposable

实现IDisposable就是实现Dispose模式。

Dispose模式:

public?class?Base?:?IDisposable

{

public?void?Dispose()

{

this.Dispose(true);

GC.SupressFinalize(this);

}

?

protected?virtual?void?Dispose(bool?disposing)

{

if?(disposing)

{

//?托管类

}

//?非托管资源释放

}

?

~Base()

{

this.Dispose(false);

}

}

?

public?class?Derive?:?Base

{

protected?override?void?Dispose(bool?disposing)

{

if?(disposing)

{

//?托管类

}

//?非托管资源释放

base.Dispose(disposing);

}

}

7.7.?对象

7.7.1.?Object.Equals

ü?要在覆盖Object.Equals方法时,遵守它定义的协定。

协定内容:

x.Equals(x)?返回true。

x.Equals(y)的返回值与y.Equals(x)相同。

如果(x.Equals(y)&&y.Equals(z))返回true,那么x.Equals(z)也应该返回true。

只要对象x和对象y未被修改,那么连续调用x.Equals(y)应该返回相同的值。

x.Equals(null)应该返回false。

?

ü?要在覆盖Equals方法的同时,覆盖GetHashCode方法。

?

ü?考虑在覆盖Object.Equals方法的同时实现IEquatable<T>接口。

?

??不要从Equals方法中抛出异常。

?

ü?要覆盖值类型的Equals方法。

?

ü?要通过实现IEquatable<T>来提供一个以值类型本身为

?

热点排行