Microsoft C#编码规范 下载本文

Page 33

{

internal Claim() { ... } }

3.10 命名空间

?一定请在一站式代码示例库中使用Visual Studio创建的项目的默认的命名空间。无需重命名命名空间为Microsoft.Sample.TechnologyName。

3.11 错误和异常

3.11.1 抛出异常

?一定请通过抛出异常来告知执行失败。异常在框架内是告知错误的主要手段。如果一个成员方法不能成功的如预期般执行,便应该认为是执行失败,并抛出一个异常。一定不要返回一个错误代码。

?一定请抛出最明确,最有意义的异常(继承体系最底层的)。比如,如果传递了一个null实参,则抛出ArgumentNullException,而不是其基类ArgumentException。抛出并捕获System.Exception异常通常都是没有意义的。

?一定不要将异常用于常规的控制流。除了系统故障或者带有潜在竞争条件的操作,您编写的代码都不应该抛出异常。比如,在调用可能失败或抛出异常的方法前,您可以检查其前置条件,举例,

// C# 示例:

if(collection != null &&!collection.IsReadOnly) {

collection.Add(additionalNumber); }

?一定不要从异常过滤器块内抛出异常。当一个异常过滤器引发了一个异常时,该异常会被CLR捕获,该过滤器返回false。该行为很难与过滤器显式的执行并返回错误区分开,所以会增加调试难度。

? 2016 Microsoft Corporation. All rights reserved.

Page 34

' VB.NET sample

' This is bad design. The exception filter (When clause) ' may throw an exception when the InnerException property ' returns null Try ...

Catch e As ArgumentException _

When e.InnerException.Message.StartsWith(\) ... EndTry

?一定不要显式的从finally块内抛出异常。从调用方法内隐式的抛出异常是可以接受的。 3.11.2 异常处理

?您不应该通过捕获笼统的异常,例如System.Exception,System.SystemException,或者.NET代码中其他异常,来隐藏错误。一定要捕获代码能够处理的、明确的异常。您应该捕获更加明确的异常,或者在Catch块的最后一条语句处重新抛出该普通异常。以下情况隐藏错误是可以接受的,但是其发生几率很低 :

Good:

// C# sample: try { ... }

catch(System.NullReferenceException exc) { ... }

catch(System.ArgumentOutOfRangeException exc) { ... }

catch(System.InvalidCastException exc) { ... }

Bad:

// C# sample: try

? 2016 Microsoft Corporation. All rights reserved.

Page 35

{ ... }

catch(Exception ex) { ... }

?一定请在捕获并重新抛出异常时,倾向使用throw 。这是保持异常调用栈的最佳途径:

Good:

// C# sample: try {

... // Do some reading with the file } catch {

file.Position = position; // Unwind on failure throw; // Rethrow }

Bad:

// C# sample: try {

... // Do some reading with the file }

catch (Exception ex) {

file.Position = position; // Unwind on failure throw ex; // Rethrow }

3.12 资源清理

?一定不要使用GC.Collect来进行强制垃圾回收。 3.12.1 Try-finally 块

?一定请使用try-finally 块来清理资源,try-catch 块来处理错误恢复。一定不要使用 catch 块来清理资源。一般来说,清理的逻辑是回滚资源(特别是原生资源)分配。举例:

? 2016 Microsoft Corporation. All rights reserved.

Page 36

// C# sample:

FileStream stream = null; try {

stream = newFileStream(...); ... } finally {

if(stream != null) stream.Close(); }

为了清理实现了IDisposable接口的对象,C# 和 VB.NET 提供了using语句来替代 try-finally 块。

// C# sample:

using(FileStream stream = newFileStream(...)) { ... }

许多语言特性都会自动的为您写入try-finally 块。例如 C#/VB的using语句, C#的lock语句, VB的SyncLock语句, C#的foreach语句以及VBFor Each 语句。 3.12.2 基础Dispose 模式

该模式的基础实现包括实现System.IDisposable接口,声明实现了所有资源清理逻辑的 Dispose(bool)方法,该方法被Dispose 方法和可选的终结器所共享。请注意,本章节并不讨论如何编写一个终结器。可终结类型是该简单模式的拓展,我们会在下个章节中讨论。如下展示了基础模式的简单实现:

// C# sample:

publicclassDisposableResourceHolder : IDisposable {

private bool disposed = false;

privateSafeHandle resource; // Handle to a resource

public DisposableResourceHolder() {

this.resource = ... // Allocates the native resource }

? 2016 Microsoft Corporation. All rights reserved.