私は.NETのコードコントラクトについて学び、純粋なコンストラクターの概念を理解しようとしています。 コードコントラクト ドキュメントには次のように記載されています。
コントラクト内で呼び出されるすべてのメソッドは、純粋でなければなりません。つまり、既存の状態を更新してはなりません。純粋なメソッドは、純粋なメソッドへのエントリ後に作成されたオブジェクトを変更することができます。
そして PureAttribute
ドキュメントはこう述べています:
型またはメソッドが純粋であることを示します。つまり、可視の状態変更を行いません。
メソッドに関してはこれらのステートメントを理解していますが、コンストラクタについてはどうですか?次のようなクラスがあるとします。
public class Foo
{
public int Value { get; set; }
public Foo(int value) {
this.Value = value;
}
}
このコンストラクターは明らかに新しいFoo
オブジェクトの状態に影響しますが、他の副作用はありません(たとえば、パラメーターを操作したり、純粋でないメソッドを呼び出したりすることはありません)。これは[Pure]
の候補ですか?コンストラクターに[Pure]
属性を配置することの重要性は何ですか。また、これを自分のコードでいつ実行する必要がありますか?
_[Pure]
_でメソッドを装飾します。
メソッドに副作用がない場合。たとえば、メソッドがデータベースにアクセスして変更する場合、またはその結果がデータベースに依存する場合、それは純粋ではありません。
Andコードコントラクトで使用する場合。たとえば、メソッドがpureであるが、コードコントラクトで使用する意図がない場合、_[Pure]
_を追加してもメリットはなく、コードは作成されませんもっと早く。
それがコンストラクターに関する限り、それらは。NETで純粋であると想定され、明示的な属性を必要としないようですDateTime
などの.NET Frameworkソースのいくつかのコンストラクタを調べましたが、それらには_[Pure]
_属性がありません。
これはいくつかの理由で行われると思います:
コントラクトでクラス/構造体を使用できるようにするためだけに、_[Pure]
_属性を使用してパラメーターなしのコンストラクターを作成する必要があるのは非現実的かもしれません。
String
などの一部には、明示的なコンストラクターがありません。
コンストラクターは、コードコントラクト以外でも特別な扱いを受けます。たとえば、 内部で例外をスローすることは想定されていません です。
_[Pure]
_は慣例にすぎませんが、この属性で修飾されたメソッドが純粋であることを確認するための実際の静的チェックはありません。 void DestroyDatabase()
は純粋であるように装飾されている場合があり、コードコントラクトは何の問題もありません。
現在、pureと宣言されたメソッドが本当に純粋かどうかをチェックするコードコントラクトのコンポーネントはありません。したがって、プログラマーが[純粋]でメソッドを装飾した場合、それは信じられています。
From コード契約#5:メソッドの純度
.NET Framework自体には、純粋ではないコンストラクターが含まれています。たとえば、 コレクションのループ に副作用がある場合、List<T>(IEnumerable<T> collection)
は実際には不正確です。
契約はシンプルに保たれるべきだと叫びます。 Contract.Requires(!string.IsNullOrEmpty(name))
などのコントラクトは簡単に想像できるので、静的_string.IsNullOrEmpty
_ピュアを宣言するのには十分な理由があります。
一方、文字列を作成するためにStringBuilder
が必要な場合は、ビジネスクラスのインスタンスメソッドを呼び出して何かを確認し、契約を誤用している可能性があります。それが _StringBuilder.ToString
_ が純粋であるとマークされていない理由でもあります(そうですか?)
この場合、オブジェクトは作成されるまで使用できません。したがって、コンストラクタは純粋です。コンストラクターが他のコードを呼び出すか、デリゲートを呼び出し、他のコードが変更可能なプロパティを変更した場合、それは純粋ではありません。安全のためには、プロパティを不変にすることをお勧めします。