2

public void Foo(string bar)呼び出し元が の null 値で呼び出してはならないメソッドがあるとしますbarprivate void FooImpl(string bar)の実際の作業を行うというメソッドも持っているとしましょうFoo。もちろん、FooImplがパブリック インターフェイスであるにもかかわらず、実際には が非 null である必要があります。そして、.NET 4.0 コード コントラクトを使用して、この非 null 性を強制したいとします。barFoo

契約書はどこに置く?

私がこれを行う場合:

public void Foo(string bar)
{
  this.FooImpl(bar);
}

private void FooImpl(string bar);
{
  Contract.Requires<ArgumentNullException>(bar != null);

  // Something that requires non-nullness, e.g.:
  bar.Contains("test");
}

Foo次に、静的チェッカーは が null の可能性がある値で呼び出していると不平を言い、FooImplnull 以外のコントラクトを に追加することを提案しFooます。わかりましたので、契約チェック/例外スローを実装メソッドに委譲することはできないと思います。

しかし、それをパブリックインターフェイスに入れようとすると、つまり:

public void Foo(string bar)
{
  Contract.Requires<ArgumentNullException>(bar != null);

  this.FooImpl(bar);
}

private void FooImpl(string bar);
{
  bar.Contains("test");
}

次に、静的チェッカーは、が null 値FooImplで呼び出さContainsれる可能性があると不平を言います---FooImplコード内で呼び出される唯一の場所がfrom であってもFoo、それ自体が null 値で呼び出されることは決してないことが保証されFooImplます。


では、同じコントラクトを 2 回含める必要がありますか? または、静的チェッカーを無視する必要がありますか? 私はそれが一種の忙しい仕事の源であり、頼りにすべきではないことを知っていますが、この基本的でおそらく一般的なシナリオを処理する何らかの方法があることを願っています.

4

2 に答える 2

3

簡単な答え: はい。

nullreference 例外などを防ぐために、コード コントラクトが必要なすべての場所に前提条件を追加する必要があります。これは、同じコントラクトを 2 回追加しているように見えることを意味する場合があります。

この特定のケースでは、FooImpl が既に前提条件を持つメソッドからのみ呼び出されることは明らかです。

ただし、静的チェッカーは、他のメソッドとは別に FooImpl メソッドを評価します。この例では、 Foo ( bar が null ではないことがわかっている場所) から bar 値を渡すだけですが、静的チェッカーは、 bar を操作していないという確実性がないため、null になる可能性があります。

また、将来、bar が null かどうかを確認するための前提条件を持たないメソッドから FooImpl メソッドを呼び出す可能性があることを考慮する必要があります。そのような場合でも、静的チェッカーで nullreference 例外が発生しないようにする必要があります。

于 2010-06-29T13:38:13.067 に答える
1

静的チェッカーをなだめるために、通常の契約関数ではなく、おそらく内部関数で Contract.Assume() を使用するため、既存の契約の正確なコピーにはなりません。その内部関数にあるときの実際の実行時チェック。

この関数が他の 1 つの場所からのみ呼び出されると推測するほどスマートではない理由については、よくわかりません。

于 2010-06-29T13:32:24.167 に答える