[FxCop.設計規則] 3. 避免定義空的接口

 

版權聲明:

 

本文由timewolf完成,首發於CSDN,作者保留版權。
未經許可,不得使用於任何商業用途。
歡迎轉載,但請保持文章及版權聲明完整。
如需聯絡請發郵件:karla9(AT)eyou(dot)com

3.     避免定義空的接口

原文引用:

Avoid empty interfaces

TypeName:

AvoidEmptyInterfaces

CheckId:

CA1040

Category:

Microsoft.Design

Message Level:

Warning

Certainty:

90%

Breaking Change:

Breaking


Cause: The interface does not declare any members or implement other interfaces.

Rule Description

Interfaces define members that provide a behavior or usage contract. The functionality described by the interface can be adopted by any type, regardless of where the type appears in the inheritance hierarchy. A type implements an interface by providing implementations for the interface's members. An empty interface does not define any members, and as such, does not define a contract that can be implemented.

If your design includes empty interfaces that types are expected to implement, you are most likely using an interface as a marker, or a way of identifying a group of types. If this identification will occur at runtime, the correct way to accomplish this is to use a custom attribute. Use the presence or absence of the attribute, or the attribute's properties, to identify the target types. If the identification must occur at compile time, then using an empty interface is acceptable.

How to Fix Violations

Remove the interface or add members to it. If the empty interface is being used to label a set of types, replace the interface with a custom attribute.

When to Exclude Messages

It is safe to exclude a message from this rule if the interface is used to identify a set of types at compile-time.

Example Code

The following example shows an empty interface.

[C#]

using System;

namespace DesignLibrary
{
   
public interface BadInterface
   
{
      
// Violates rule: AvoidEmptyInterfaces.
   }

}

 

引發原因:

一個接口沒有任何成員,且沒有繼承其他接口

規則描述:

接口定義了一組成員,用以描述接口擁有的行爲或契約(usage contract)任何類型都可以實現該接口, 無需考慮該類的繼承層次。一個類通過實現接口的成員從而實現接口。一個空的接口沒有定義任何成員,因此,也就沒有任何契約能夠被實現。

如果你的設計包含空的接口,並希望它被某些類實現,你很可能是將該接口作爲一個標記,用以標示一組類型。如果只需在運行時區分這些類型,你可以使用自定義特性(attribute)。通過檢查某個類是否包含該特性,以及特性所包含的屬性(property),來達到識別某個類的目的;當然,如果你希望在編譯期就執行此種檢查,就只好使用空接口了。

修復:

刪除該接口,或添加必要的成員到該接口。

如果該接口被用於運行時的類型識別,將接口替換爲自定義特性。

譯註:

自定義特性是.NET新引入的一種開發元素,通過將自定義特性和應用程序元數據保存在一起,開發人員可以獲得類似自定義關鍵字的能力。以下是MSDN中對於特性的描述:

如果您使用過 C++,您或許對包含關鍵字(如 public private)的聲明比較熟悉。這些關鍵字提供有關類成員的附加信息,還通過描述類成員對其他類的可訪問性來進一步定義類成員的行爲。由於編譯器被顯式設計爲識別預定義關鍵字,因此傳統上您沒有機會創建自己的關鍵字。但是,公共語言運行庫允許您添加類似關鍵字的描述性聲明(稱爲特性)來批註編程元素,如類型、字段、方法和屬性。

爲運行庫編譯代碼時,該代碼被轉換爲 Microsoft 中間語言 (MSIL),並同編譯器生成的元數據一起被放到可移植可執行 (PE) 文件的內部。特性使您得以向元數據中放置額外的描述性信息,並可使用運行庫反射服務提取該信息。當您聲明從 System.Attribute 派生的特殊類的實例時,編譯器創建特性。

.NET Framework 出於多種原因使用特性並通過它們解決若干問題。特性可以描述如何序列化數據,指定用於強制安全性的特性,以及限制實時 (JIT) 編譯器的優化以使代碼易於調試。特性還可以記錄文件名或代碼作者,或在窗體開發階段控制控件和成員的可見性。

可使用特性以幾乎所有可能的方式描述代碼,並以富有創造性的新方式影響運行庫行爲。特性允許您向 C#C++ 託管擴展、Microsoft Visual Basic .NET 或其他任何以運行庫爲目標的語言添加自己的描述性元素,而不必重新編寫編譯器。

使用特性可以獲得很大的開發靈活性,並且可以提供很多非常清晰易讀的代碼,筆者看到的在NUnit中的一段代碼可以作爲使用特性的很好例子:
上面的例子中,基類裏通過自定義特性分析命令行參數,並將他們分別填充到字段中。例如用戶輸入下面的命令行參數:

namespace NUnit.Util
{
     
using System;
     
using Codeblast;

     
public class ConsoleOptions : CommandLineOptions
     
{
         [Option(Description 
= "Fixture to test")]
         
public string fixture;

         [Option(Description 
= "Project configuration to load")]
         
public string config;
 
         [Option(Description 
= "Name of XML output file")]
         
public string xml;
 
         [Option(Description 
= "Name of transform file")]
         
public string transform;
 
         [Option(Description 
= "Display XML to the console")]
         
public bool xmlConsole;
     }

}


NUnit-Console.exe /config:a.cfg

基類就會將“a.cfg”填充到config變量中。

相關的代碼可以參考NUnit/nunit.util.dll/CommandLineOption.cs NUnit/nunit.util.dll/ConsoleOption.cs

發佈了32 篇原創文章 · 獲贊 3 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章