8

不変性がどのように定義されているのだろうか?値がパブリックとして公開されていないため、変更できない場合は、それで十分ですか?

型の顧客ではなく、型内で値を変更できますか?

それとも、コンストラクター内でのみ設定できますか? もしそうなら、二重初期化の場合 (this構造体でキーワードを使用するなど) は、不変型に対してまだ問題ありませんか?

型が 100% 不変であることをどのように保証できますか?

4

10 に答える 10

23

値がパブリックとして公開されていないため、変更できない場合は、それで十分ですか?

いいえ、読み取りアクセスが必要なためです。

型の顧客ではなく、型内で値を変更できますか?

いいえ、それはまだ突然変異だからです。

それとも、コンストラクター内でのみ設定できますか?

ディンディンディン!不変型には、多くの場合、新しいインスタンスを構築して返すメソッドがありinternal、それらのメソッドで使用するために特別にマークされた追加のコンストラクターがあることが多いという追加のポイントがあります。

型が 100% 不変であることをどのように保証できますか?

.Net では、リフレクションを使用してプライベート メンバーを変更 (変更) できるため、このような保証を得るのは難しいです。

于 2009-05-26T21:31:29.647 に答える
7

以前の投稿者は、コンストラクターでフィールドに値を代入してから手を離す必要があると既に述べています。しかし、それは言うは易く行うは難しです。不変オブジェクトが type のプロパティを公開しているとしましょうList<string>。そのリストは変更できますか? そうでない場合、どのように制御しますか?

Eric Lippert は、C# の不変性に関する一連の投稿を彼のブログに書いています。興味深いかもしれません。最初の部分は、こちら にあります

于 2009-05-26T21:36:44.503 に答える
5

これらすべての回答で見逃されている可能性があると思うことの 1 つは、オブジェクトの内部状態が変化しても、それらの内部変化が「クライアント」コードに表示されない限り、オブジェクトは不変であると見なすことができると思うことです。

たとえば、System.Stringクラスは不変ですが、インスタンスのハッシュ コードをキャッシュすることは許可されているので、ハッシュは への最初の呼び出しでのみ計算されGetHashCode()ます。私の知る限り、System.Stringクラスはこれを行いませが、不変と見なされる可能性があることに注意してください。もちろん、これらの変更はいずれも、スレッドセーフな方法で処理する必要があります (変更の観察不可能な側面に合わせて)。

正直なところ、この種の「目に見えない可変性」が必要な理由や必要な理由はあまり思いつきません。

于 2009-05-27T00:35:34.627 に答える
3

ウィキペディアからの不変性の定義は次のとおりです(リンク

「オブジェクト指向および関数型プログラミングでは、不変オブジェクトは、作成後に状態を変更できないオブジェクトです。」

基本的に、オブジェクトが作成されると、そのプロパティを変更することはできません。例は String クラスです。String オブジェクトが作成されると、変更することはできません。それに対して行われた操作は、実際には新しい String オブジェクトを作成します。

于 2009-05-26T21:32:03.000 に答える
3

そこにはたくさんの質問があります。私はそれらのそれぞれに個別に答えようとします:

  • 「不変性はどのように定義されているのだろうか?」-ウィキペディアのページから直接(および完全に正確/簡潔な定義)

    不変オブジェクトは、作成後に状態を変更できないオブジェクトです

  • 「値が公開されていないため、変更できない場合は、それで十分ですか?」- そうではありません。いかなる方法でも変更できないため、メソッド/関数がオブジェクトの状態を変更しないようにし、操作を実行する場合は常に新しいインスタンスを返す必要があります。

  • 「型の顧客ではなく、型の内部で値を変更できますか?」- 技術的には、型の内部またはコンシューマーによって変更することはできません。System.String実際には、理論上ではありませんが、ほとんどすべての実用的な目的で変更可能と見なすことができる (問題の参照型)などの型が存在します。

  • 「または、コンストラクター内でのみ設定できますか?」- はい、理論的には、状態 (変数) を設定できる唯一の場所です。

  • 「もしそうなら、二重初期化の場合 (構造体で this キーワードを使用するなど) は、不変型に対してまだ問題ありませんか?」- はい、それでもまったく問題ありません。これはすべて初期化 (作成) プロセスの一部であり、完了するまでインスタンスは返されないためです。

  • 「型が 100% 不変であることをどのように保証できますか?」- 次の条件は、それを保証する必要があります。(抜けていたら誰か指摘してください。)

    1. 変数を公開しないでください。それらはすべて保持する必要がありますprivateprotected派生クラスは状態を変更できるため、受け入れられません)。
    2. インスタンス メソッドが状態 (変数) を変更することを許可しないでください。これはコンストラクターでのみ行う必要がありますが、「変更された」オブジェクトを返す必要がある場合、メソッドは特定のコンストラクターを使用して新しいインスタンスを作成する必要があります。
    3. (読み取り専用として) 公開されるすべてのメンバー、またはメソッドによって返されるオブジェクトは、それ自体が不変である必要があります。

    注: 派生型は新しい変数を定義できるため、派生型の不変性を保証することはできません。sealedこれは、派生クラスがコード内のどこでもベースの不変型であると見なされないように、不変であることを確認したくない型をマークする理由です。

それが役立つことを願っています。

于 2009-05-26T21:36:04.287 に答える
1

残念ながら、c#/ vb.netには不変のキーワードはありませんが、議論されていますが、autopropertiesがなく、すべてのフィールドが読み取り専用(読み取り専用フィールドはコンストラクターでのみ割り当てられる)modfierで宣言され、すべてのフィールドが宣言されている場合自己不変性を保証する不変型。

于 2009-05-27T06:06:58.280 に答える
1

不変オブジェクトとは、もっともらしいコード実行シーケンスによって監視可能な状態が決して変更されないオブジェクトです。不変型とは、外部の世界に公開されるすべてのインスタンスが不変であることを保証する型です (この要件は、オブジェクトの状態がそのコンストラクターでのみ設定される必要があるとよく言われます。これは、また、構築中に外部メソッドを呼び出すオブジェクトの場合も十分ではありません)。

ただし、他の回答が無視している点は、オブジェクトの状態の定義です。Fooがクラスの場合、 の状態は、そこに含まれるList<Foo>一連のオブジェクト IDで構成されます。特定のインスタンスへの唯一の参照が、List<Foo>そのシーケンスを変更せず、変更する可能性のあるコードに公開しないコードによって保持されている場合、そのインスタンスは、Fooその中で参照されているオブジェクトが変更可能かどうかに関係なく、不変になります。不変。

例えるなら、自動車の VIN (Vehicle Identification Numbers) のリストが改ざん防止用紙に印刷されている場合、自動車はそうではありませんが、リスト自体は不変です。リストに今日赤い車が 10 台含まれていても、明日には青い車が 10 台含まれる可能性があります。ただし、それでも同じ 10 台の車になります。

于 2012-08-14T22:59:33.027 に答える
1

不変性とは、コンストラクターですべてを設定し、後でオブジェクトの有効期間中に変更できない場合であることを学びました。

于 2009-05-26T21:32:47.663 に答える
1

不変性の定義はGoogleにあります。

例:

不変 - 文字通り、変更できません。
www.filosofia.net/materiales/rec/glosaen.htm

イミュータブルなデータ構造に関して言えば、典型的な定義は write-once-read-many です。つまり、あなたが言うように、一度作成すると変更することはできません。

若干グレーゾーンに入るケースもあります。たとえば、.NET 文字列は変更できないため不変と見なされますが、StringBuilder は String オブジェクトを内部的に変更します。

于 2009-05-26T21:33:49.970 に答える
1

不変は本質的に、それ自身のコード内から強制的に final になるクラスです。それがそこにあると、何も変更できません。私の知る限り、物事はコンストラクターで設定され、それで終わりです。そうでなければ、何かがどのように不変になるのかわかりません。

于 2009-05-26T21:34:27.520 に答える