web-dev-qa-db-ja.com

C#:NotNullおよびCanBeNull属性を実装および使用する方法

メソッドがnullを必要としないことをプログラマーと私に知らせたいです。とにかくnullを送信しても、結果はきれいではありません。

Lokad Shared Libraries にはNotNullAttributeCanBeNullAttributeがあり、Lokad.Quality名前空間。

しかし、それはどのように機能しますか?これら2つの属性のソースコードを調べたところ、次のようになっています。

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter |
                AttributeTargets.Property | AttributeTargets.Delegate |
                AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
[NoCodeCoverage]
public sealed class NotNullAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter |
                AttributeTargets.Property | AttributeTargets.Delegate |
                AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
[NoCodeCoverage]
public sealed class CanBeNullAttribute : Attribute
{
}

Attributeから継承する2つの空のクラス。それらはどのように使用されますか? xml-documentationを調べて、それがあることを知っている必要がありますか?原因私は属性の独自のコピーを作成し、Lokadバージョンを使用しようとしましたが、nullを直接送信しようとしても、メッセージが表示されませんでした。 ReSharperからもVSからも。実際に私はそれを期待していました。しかし、それらはどのように使用されますか? nullであるものを送信しようとすると、VSに警告を生成させることができますか?それとも、ある種のテストフレームワークで使用されているだけですか?それとも?

40
Svish

中期的には、「4.0での」「コードコントラクト」がこれに対するより良い答えになります。それらは現在利用可能です( academic または commercial ライセンスで)、VS2010でより統合されます。これにより、静的解析とランタイムサポートの両方を提供できます。

(編集)例:

Contract.RequiresAlways( x != null );

簡単なことです...コードコントラクトエンジンはILレベルで動作するため、ビルド中または実行時にコードを呼び出すことにより、それを分析し、警告/エラーをスローできます。後方互換性のために、既存の検証コードがある場合は、健全性チェックが終了する場所を伝えるだけで、残りは処理されます。

if ( x == null ) throw new ArgumentNullException("x");
Contract.EndContractBlock();
46
Marc Gravell

これは [〜#〜] aop [〜#〜] で行うことができます。これにより、実行時にメソッドパラメータがnullであるかどうか、nullが許可されるかどうかが検証されます。 AOPについては PostSharp および Spring.NET をご覧ください。

ReSharperについては、 注釈付きフレームワーク を参照してください。

私たちは、.NET FrameworkクラスライブラリとNUnit Frameworkの大部分を分析し、JetBrains.Annotations名前空間のカスタム属性のセットを使用して、外部XMLファイルを通じて注釈を付けました。

  • StringFormatMethodAttribute(フォーマット文字列をパラメーターとして取るメソッドの場合)
  • InvokerParameterNameAttribute(呼び出し元パラメーターの1つと一致する必要のある文字列リテラル引数を持つメソッドの場合)
  • AssertionMethodAttribute(アサーションメソッド用)
  • AssertionConditionAttribute(アサーションメソッドの条件パラメーター用)
  • TerminatesProgramAttribute(制御フローを終了するメソッドの場合)
  • CanBeNullAttribute(nullの可能性がある値の場合)
  • NotNullAttribute(nullにできない値の場合)
19
Anton Gogolev

これらの注釈はReSharper用であり、JetBrains.Annotations名前空間からコピーされます。フレームワークはそれらを独自の名前空間に置くことができますが、ReSharperはこれらの注釈を自動的に取得しません-オプションダイアログでカスタム名前空間を使用するようReSharperに指示する必要があります。新しい名前空間を選択すると、ReSharperの分析により属性が取得され、ハイライトと警告が表示されます。

8
citizenmatt

Anton Gogolev で指摘されているように、属性はPostSharpを使用して作成できます(CodeContractはメソッド本体内で静的メソッド呼び出しを使用していることに注意してください)

2013年2月の更新:PostSharpの新しい3.0リリース(現在ベータ版)は、 パラメータ、フィールド、およびプロパティの検証 をサポートします

1)記事 validate-parameters-using-attributes の実装

パブリッククラスNotEmpty:ParameterAttribute

パブリッククラスNotNull:ParameterAttribute

[AttributeUsage(AttributeTargets.Parameter)]

パブリック抽象クラスParameterAttribute:属性

{

public abstract void CheckParameter(ParameterInfo parameter, object value); 

}

また、パラメーター属性を処理するために、メソッド境界アスペクトを持つメソッド属性が必要でした。

2)記事へのコメントには、 非常に類似した実装 for NonNull/NonEmptyへのリンクがあります

[戻り値:NonNull] public SomeObject SomeMethod([NonNull] AnotherObject param1)

ソースコードは次の場所にあります google code Torch/DesignByContract

3)別のより複雑な例は、 http://badecho.com/2011/11/validating-method-parameters-with-postsharp/ で説明されています

3