续之二,IDesign C#编码规范之三。
34. 避免使用new继承修饰符,而是使用override。
Avoid using the new inheritance qualifier. Use override instead.
35. 对非密封类总是将public和protected方法标记为virtual。
Always mark public and protected methods as virtual in a non sealed class.
36. 除非涉及到互操作,永远不要用不安全的代码。
Never use unsafe code unless when using interop.
37. 避免显式类型转换。使用as算法防护性地转换类型。
Avoid explicit casting. Use the as operator to defensively cast to a type.
Dog dog = new GermanShepherd();
GermanShepherd shepherd = dog as GermanShepherd;
if(shepherd != null)
{...}
38. 类成员有委托时:
With delegates as class members:
a) 使用前将委托复制到局部变量,以避免并发冲突。
Copy a delegate to a local variable before publishing to avoid concurrency race condition.
b) 调用前始终检查委托是否为空。
Always check a delegate for null before invoking it.
public class MySource
{
public event EventHandler MyEvent;
public void FireEvent()
{
EventHandler temp = MyEvent;
if(temp != null)
{
temp(this,EventArgs.Empty);
}
}
}
39. 不要提供public的事件成员变量,而是使用事件访问器。
Do not provide public event member variables. Use event accessors instead.
public class MySource
{
MyDelegate m_SomeEvent;
public event MyDelegate SomeEvent
{
add
{
m_SomeEvent += value;
}
remove
{
m_SomeEvent -= value;
}
}
}
40. 使用Programming .NET Components中定义的EventsHelper类安全地发布事件。
Use the EventsHelper class defined in Programming .NET Components to publish events defensively.
41. 总是使用接口。
Always use interfaces.
a) 参见Programming .NET Components第一和第三章。
See Chapters 1 and 3 in Programming .NET Components.
42. 类和接口中方法和属性的比例至少是2:1。
Classes and interfaces should have at least 2:1 ratio of methods to properties.
43. 避免使用一个成员的接口。
Avoid interfaces with one member.
44. 努力使每个接口拥有3-5个成员。
Strive to have 3-5 members per interface.
45. 每个接口不用超过20个成员。
No more than 20 members per interface.
a) 12可能是实际应用的极限了。
12 is probably a practical limit.
46. 避免将事件作为接口成员。
Avoid events as interface members.
47. 避免使用抽象方法,而是使用接口代替。
Avoid abstract methods, use interfaces instead.
48. 在类层次中暴露接口。
Expose interfaces on class hierarchies.
a) 参见Programming .NET Components第三章。
See Chapter 3 in Programming .NET Components.
49. 优先使用明确的接口实现。
Prefer using explicit interface implementation.
a) 参见Programming .NET Components第三章。
See Chapter 3 in Programming .NET Components.
50. 永远不要假设一种类型支持某个接口。防护性地检查是否支持该接口。
Never assume a type supports an interface. Defensively query for that interface.
SomeType obj1;
IMyInterface obj2;
/* Some code to initialize obj1, then: */
obj2 = obj1 as IMyInterface;
if(obj2 != null)
{
obj2.Method1();
}
else
{
//Handle error in expected interface
}
51. 将呈现给用户的字符串永远不用硬编码,而是使用资源。
Never hardcode strings that will be presented to end users. Use resources instead.
52. 发布时可能修改的字符串永远不用硬编码,例如连接字符串。
Never hardcode strings that might change based on deployment such as connection strings.
53. 构建一个长字符串时,使用StringBuilder,不要用string。
When building a long string, use StringBuilder, not string.
54. 避免提供带结构的方法。
Avoid providing methods on structures.
a) 参数化的构造函数是鼓励使用的。
Parameterized constructors are encouraged.
b) 可以重载算符。
Can overload operators.
55. 当提供静态成员变量时,总是提供一个静态构造函数。
Always provide a static constructor when providing static member variables.
56. 只要可以用前期绑定就不要用后期绑定。
Do not use late-binding invocation when early-binding is possible.
57. 对应用程序进行日志和跟踪。
Use application logging and tracing.
58. 除非在switch语句中跳转,永远不要用goto语句。
Never use goto unless in a switch statement fall-through.
59. switch语句中总是使用default用于加断言。
Always have a default case in a switch statement that asserts .
int number = SomeMethod();
switch(number)
{
case 1:
Trace.WriteLine("Case 1:");
break;
case 2:
Trace.WriteLine("Case 2:");
break;
default:
Debug.Assert(false);
break;
}
60. 除非在构造函数中调用另一个构造函数,否则不用使用this。
Do not use the this reference unless invoking another constructor from within a constructor.
//Example of proper use of this
public class MyClass
{
public MyClass(string message)
{}
public MyClass() : this("hello")
{}
}
61. 除非为了解决调用基类构造函数时成员名的冲突,否则不要使用base访问基类的成员。
Do not use the base word to access base class members unless you wish to resolve a conflict with a subclasses member of the same name or when invoking a base class constructor.
//Example of proper use of 抌ase?
public class Dog
{
public Dog(string name)
{}
virtual public void Bark(int howLong)
{}
}
public class GermanShepherd : Dog
{
public GermanShepherd(string name): base(name)
{}
override public void Bark(int howLong)
{
base.Bark(howLong);
}
}
62. 根据Programming .NET Components第四章中的模板实现Dispose()和Finalize()方法。
Implement Dispose() and Finalize() methods based on the template in Chapter 4 of Programming .NET Components.
63. 使用泛型的代码中避免与System.Object进行类型转换,而是使用限制或as算符。
Avoid casting to and from System.Object in code that uses generics. Use constraints or the as operator instead:
class SomeClass
{}
//避免 Avoid:
class MyClass
{
void SomeMethod(T t)
{
object temp = t;
SomeClass obj = (SomeClass)temp;
}
}
//正确 Correct:
class MyClass where T : SomeClass
{
void SomeMethod(T t)
{
SomeClass obj = t;
}
}
64. 泛型接口不要定义限制。接口层的限制通常能用强类型代替。
Do not define constraints in generic interfaces. Interface level-constraint can often be replaced by strong-typing.
public class Customer
{...}
//避免 Avoid:
public interface IList where T : Customer
{...}
//正确 Correct:
public interface ICustomerList : IList
{...}
65. 不要在接口中定义与方法相关的限制。
Do not define method-specific constraints in interfaces.
66. 在数据结构中总是优先使用C#泛型。
Always prefer using C# generics in data structures.
(待续)