2014-05-08 93 views
14

同一個枚舉的多枚舉是我們遇到的一個性能問題,所以我們嘗試在代碼中踩踏這些警告。但是我們有一個通用的擴展函數,用於引發生成很多這些警告的空參數異常。它的簽名是這樣的:我可以標記C#函數爲「此函數不枚舉IEnumerable參數」嗎?

public static void VerifyArgumentIsNotNull<T>(this T value, string valueName) where T : class 

它所做的就是檢查null,並拋出一個很好的格式化和本地化(無論哪個人的語言是在比賽的時候)例外。

在IEnumerable參數上使用此函數時,它會使代碼分析警告IEnumerable可能發生多次迭代,因爲分析器不知道該函數的作用。

我想在這個函數上加上一些標籤,上面寫着:「是的,這將可枚舉作爲輸入,但它不會迭代它,因此不應該被調用者視爲可能的迭代。有沒有這樣的標籤?我搜索了互聯網無濟於事。

回答

18

是的,你問的是非常可能的,但需要一點點工作。 ReSharper使用Code Annotations爲其分析引擎添加提示,並更好地瞭解它必須使用的代碼。我最近錄製了一個名爲ReSharper Secrets的JetBrains網絡研討會,在這裏我詳細介紹了註釋是什麼以及如何使用它們。你應該看!

有註釋屬性,[NoEnumeration]已經做了你問什麼 - 指定給定IEnumerable參數不一一列舉,但是它不包含在默認Code Annotation Attributes,但它是在JetBrains.Annotations.dll組件定義。

所以本次的介紹後,這裏就是你需要做的:

  1. (如果您還沒有),進入ReSharper的選項,那麼代碼檢查→代碼註釋,然後按複製默認實現到剪貼板按鈕
  2. 創建任何名爲Annotations.cs你(共享)項目的文件(或任何其他名稱)
  3. 代碼從剪貼板粘貼,完全取代任何先前在Annotations.cs
  4. 添加以下定義在文件的結尾:

代碼:

/// <summary> 
/// Indicates that IEnumarable, passed as parameter, is not enumerated. 
/// </summary> 
[AttributeUsage(AttributeTargets.Parameter)] 
public sealed class NoEnumerationAttribute : Attribute 
{ 
} 

你做到了這一點之後,所有剩下要做的就是放置[NoEnumeration]屬性上value的說法,這樣的:

public static void VerifyArgumentIsNotNull<T>([NoEnumeration] this T value, string valueName) where T : class 
{ 
    .... 
} 

就是這樣!警告將消失!

獎勵:

有3個可以用來裝點這個方法的附加屬性,使之更加有用:[NotNull][ContractAnnotation][InvokerParameterName]。我最近描述了他們在this issue中爲一個名爲LiteGuard的類似API做了什麼(和一個簡短的演示)。

註解是樂趣:)

+0

>(如果您還沒有),進入ReSharper的選項,那麼代碼檢查→代碼註釋,並按下此默認實現到剪貼板按鈕 R·8.2能夠自動做到這一點。 – hazzik

+0

@hazzik如何? (我知道,這將導入的註釋,如果我實現INPC,但怎麼回事?) –

+0

一位同事關心究竟這種解決方案會做我們的代碼庫 - 通過添加Annotations.cs,是我們以某種方式使我們的可執行文件在運行時依賴於一些新的DLL?我不太瞭解代碼屬性或jetbrains實現來回答這個問題。 – srm

0

假設您在代碼分析窗口中使用Visual Studio 2013/2012(我只知道2013年的此功能),您應該可以右鍵單擊該消息導航到抑制消息>在源文件中在抑制文件中

或者,您也可以通過在代碼分析窗口中單擊消息的操作下拉菜單來實現相同的效果。

+2

這不利於抑制...只幫助在主叫方,他們會抑制合法的多個枚舉警告。我需要一些註解被調用者的東西,所以沒有調用者在第一個地方*從這個被調用者*獲得警告。 – srm

2

由於VerifyArgumentIsNotNull是通用的,但什麼都不做具體類型,它可以採取一個對象:(9.11)

public static void VerifyArgumentIsNotNull(this object @object, string argumentName) { ... } 

ReSharper的假定調用的方法不投@object回到IEnumerable,因此沒有警告。

注意缺少類約束意味着如果您不小心將值類型傳遞給VerifyArgumentIsNotNull,編譯器可能不會發出警告,但Resharper將警告值類型永遠不能爲null。

這種方法還有另外一個好處,就是保存JIT爲VerifyArgumentIsNotNull被調用的每個類型創建一個實例(封閉泛型)方法;一個微觀優化是肯定的,但是一個罕見的例子,其中一個通用可能不會比老派對象更可取。

上面的一個可能的缺點:我見過類似的實現,其中VerifyArgumentIsNotNull返回「值」。在這種情況下,需要類型T的返回值以避免顯式強制轉換。 (國際海事組織的這種語法很醜,所以對我來說這不是一個缺點)

另外兩篇編輯點評: 1.我看過的一個方法名:ThrowIfNull更簡潔,「Throw」比「驗證「 2.我不再使用此方法,因爲沒有VerifyArgumentIsNotNull上的批註,否則resharper必須假定參數仍然可以爲null。我發現讓R#更簡單,在添加NotNullAttribute時插入1行的if + throw。

這種方法不適合要確保一個方法調用可枚舉的更廣泛的情況下工作。在這種情況下,Igal Tabachnik添加註釋很棒。

相關問題