コンストラクターで[Pure]を使用する場合


19

.NETのコードコントラクトについて学び、純粋なコンストラクターの概念を理解しようとしています。コードの契約ドキュメントの状態:

コントラクト内で呼び出されるすべてのメソッドは純粋でなければなりません。つまり、既存の状態を更新してはなりません。純粋メソッドでは、純粋メソッドへのエントリ後に作成されたオブジェクトを変更できます。

そして、PureAttributeドキュメントの状態:

型またはメソッドが純粋であること、つまり、目に見える状態の変更を行わないことを示します。

メソッドに関してはこれらのステートメントを理解していますが、コンストラクターはどうですか?次のようなクラスがあったとします:

public class Foo
{
    public int Value { get; set; }

    public Foo(int value) {
        this.Value = value;
    }
}

このコンストラクターは明らかに新しいFooオブジェクトの状態に影響しますが、他の副作用はありません(たとえば、パラメーターを操作したり、非純粋なメソッドを呼び出したりしません)。これは候補者[Pure]ですか?[Pure]コンストラクターに属性を配置することの意義は何ですか?また、自分のコードでこれをいつ行う必要がありますか?

回答:


14

メソッドを装飾するには[Pure]

  • メソッドに副作用がない場合。たとえば、メソッドがデータベースにアクセスして変更したり、その結果がデータベースに依存している場合、それは純粋ではありません。

  • また、コードコントラクトで使用する予定がある場合。たとえば、メソッドがpureであるが、コードコントラクトで使用する意図がない場合、追加[Pure]してもメリットはなく、コードを高速化することはできません。

コンストラクタに関する限り、それらは.NETで純粋であると想定されており、明示的な属性を必要としないようです。などの.NET Frameworkソースのいくつかのコンストラクターを調べましたがDateTime、それらには[Pure]属性がありません。

これはいくつかの理由で行われていると思います。

  • [Pure]コントラクトでクラス/構造体を使用できるようにするために、属性付きのパラメーターなしのコンストラクターを記述する必要があるのはあまりにも非現実的かもしれません。

  • などString、明示的なコンストラクタがないものもあります。

  • コンストラクターは、コードコントラクト以外でも特別な扱いを受けます。たとえば、それらの内部で例外をスローすることは期待されていません

  • [Pure]これは単にあなたの人生を単純化するための慣例ですが、この属性で装飾されたメソッドが純粋であることを確認するための実際の静的チェックはありません。void DestroyDatabase()純粋であると装飾されている可能性があり、コードコントラクトは何も間違っていることに気付かないでしょう。

    現在、純粋と宣言されたメソッドが実際に純粋であるかどうかをチェックするコードコントラクトのコンポーネントはありません。したがって、プログラマーがメソッドを[Pure]で装飾した場合、それは信じられています。

    コード#5コントラクト:メソッドの純度

  • .NET Framework自体には、純粋ではないコンストラクタが含まれています。たとえば、コレクションのループに副作用があるList<T>(IEnumerable<T> collection)場合、実際には不純です。

  • 契約はシンプルに保ってください。のようなコントラクトは簡単に想像できるContract.Requires(!string.IsNullOrEmpty(name))ので、静的string.IsNullOrEmptyピュアを宣言する正当な理由があります。

    一方、StringBuilder文字列を作成するために必要な場合は、ビジネスクラスのインスタンスメソッドを呼び出して何かを確認し、おそらくコントラクトを誤って使用していることになります。それStringBuilder.ToStringは、たとえそれがそうであるかもしれないとしても、それが純粋であるとマークされない理由でもあります(そうですか?)


契約チェッカーは、「System.Diagnostics.Contracts.Contract」、「System.String」、「System.IO.Path」、または「System .Type " "。残念ながら、コードコントラクトに関しては、.NETタイプを見るのがあまりに便利かどうかわかりません。
pswg 14

3
純度は、呼び出されたコードもすべて純粋でなければならない、または呼び出し元が「純粋」ではないものの1つです。すべてのコンストラクターがデフォルトで純粋であると考えるのは難しいと思います。
フランクヒルマン14

@FrankHileman:私も。現在、C#コンパイラーはありませんが、コンストラクターと[Pure]属性なしでクラスを記述し、それを契約の別の場所で使用して決定的な答えを得ることができます。
Arseni Mourzenko

1

この場合、オブジェクトは構築されるまで使用できません。したがって、コンストラクターは純粋です。コンストラクタが他のコードを呼び出したり、デリゲートを呼び出したり、他のコードが可変プロパティを変更した場合、それは純粋ではありません。より安全にするために、プロパティを不変にすることをお勧めします。


それで、純粋なコンストラクタは、純粋であるという他の条件を満たす限り、現在のクラスの状態を変更できる純粋なメソッドですか?ところで、このクラス自体は純粋ではないことを強調したかったため、このプロパティは変更可能です。
pswg 14

@pswg:おそらくマイクロソフトが答える必要のある興味深い質問を作成しました。コンストラクターが可変プロパティを変更するメソッドを呼び出したとします。コンストラクタはまだ純粋でしょうか?外部の視聴者には変更が「見えない」にもかかわらず、技術的にはそうではないと思います。元の例では他のコードは呼び出されないため、考えられる定義では純粋でなければなりません。
フランクヒルマン14

@pswg:プロパティセットがメソッド呼び出しでもあることを除きます。MSDNフォーラムで質問する必要があると思います。
フランクヒルマン14

純粋さの中心的な考え方が、メソッドが目に見える変化を起こすかどうかである場合、その意味では、非純粋なメソッドを呼び出すかどうかに関係なく、呼び出し元がその変化を観察できない限り、それはまだ純粋な方法です。
pswg 14

@pswg:それは抽象的な定義です。ただし、これらのアナライザーを作成している場合、おそらく呼び出し元を非純粋にするために非純粋メソッド呼び出しも考慮されるでしょう。実装を簡単にするためだけに。質問は、コンストラクターが通常のメソッド呼び出しであるか、または分析がどの程度行われるかです。
フランクヒルマン14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.