16

クラスがC#で不変かどうかを調べるにはどうすればよいですか?

4

7 に答える 7

34

ありますがImmutableObjectAttribute、これはめったに使用されず、サポートも不十分です。もちろん、強制されません([ImmutableObject(true)].AFAIKで可変オブジェクトをマークできます。これが影響するのは、IDEが属性を処理する方法(つまり、表示/非表示)だけです。名前付きプロパティオプション)。

実際には、をチェックする必要がありますがFieldInfo.IsInitOnly、これは本当に100%不変のタイプにのみ適用されます(反射の乱用などがないと仮定)。アイスキャンデーの不変性や、実際には不変であるが実装では役に立たないものには役立ちません。つまり、それらを公的に変更可能にすることはできませんが、理論的にはオブジェクトはそれをサポートします。

stringここでの典型的な例は文字列です...誰もが不変であることを「知っています」StringBuilder ...もちろん、ボンネットの下の文字列を変更します。いいえ、真剣に...

これを考えると、不変性を定義するのは非常に困難です。それを確実に検出することは言うまでもありません...

于 2009-01-27T00:43:58.330 に答える
4

問題の一部は、「不変」が複数の意味を持つ可能性があることです。たとえば、ReadOnlyCollection<T>を考えてみましょう。

私たちはそれを不変であると考える傾向があります。しかし、それがReadOnlyCollection <SomethingChangeable>の場合はどうなるでしょうか?また、これは実際にはコンストラクターに渡すIListの単なるラッパーなので、元のIListを変更するとどうなりますか?

良いアプローチは、ReadOnlyAttributeのような名前で属性を作成し、それを使用して読み取り専用と見なすクラスにマークを付けることです。制御しないクラスについては、不変であると見なす既知のタイプのリストを維持することもできます。

編集:さまざまなタイプの不変性のいくつかの良い例については、Eric Lippertによるこの一連の投稿を読んでください:http://blogs.msdn.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one -kinds-of-immutability.aspx

于 2009-01-27T00:43:12.937 に答える
3

あなたはできません、あなたは推測することしかできません。すべてのフィールドが読み取り専用の場合、コンストラクターが終了すると、インスタンスは不変になります。これは重要です。次の場合、インスタンスバーに対して変更可能に見えます。

class Foo
{
    public readonly int X
    public readonly int Y
    public Foo(int x, int y, Bar bar)
    {
        this.X = x; 
        bar.ShowYourself(this);
        this.Y = y;
        bar.ShowYourself(this);
    }
}

ただし、不変と思われるクラスのフィールドがコレクションである(読み取り専用ではない)場合、クラスを不変と呼ぶのは正しくない可能性があります(状態が変更される可能性があるため)

すべてのフィールドが読み取り専用であっても、リフレクションはフィールドを変更できることに注意してください。

プロパティにセッターがないかどうかをチェックすることは、実際には非常に貧弱なヒューリスティックになります。

于 2009-01-27T00:34:43.327 に答える
2

私の知る限り、明示的に文書化されていない限り、C# でクラスが不変かどうかを判断する方法はありません。

ただし、Reflection を使用して、プロパティの Setter の存在を確認できます。ただし、明示的に設定できるかどうかにかかわらず、内部状態によってこれらのプロパティの値が変更される可能性があるため、セッターがないからといって不変性が保証されるわけではありません。

さらに、クラスのすべてのフィールドの「IsInitOnly」フラグを再度 Reflection を使用してチェックすると、不変性が示される可能性がありますが、それを保証するものではありません。

編集: Java言語に関して尋ねられた同様の質問があります。その回答はここにも当てはまります。

于 2009-01-27T00:19:12.703 に答える
1

コードを介して、私にはわかりませんが、文字列などの別の不変タイプのILを見ると ILnewobj命令は表示されません(文字列の場合はldstrが表示されます)。おそらく作成のILを検査します。一つの方法かもしれませんが、推測です...

于 2009-01-27T00:42:58.863 に答える
1

ランタイムから得られる唯一のヘルプは、クラス内のすべてのフィールドに「読み取り専用」の注釈が付けられている場合です。[編集、@ShuggyCoUk を参照] それでも、CLR を使用すると上書きできます。確認しただけです。うーん。

リフレクションを介してクラスから FieldInfo オブジェクトを取得し、IsInitOnly を確認できます。

于 2009-01-27T00:20:36.630 に答える