web-dev-qa-db-ja.com

C#デリゲートは不変ですが、なぜそれが重要なのですか?

これはこの他の質問のフォローアップ質問です。

背景

MSDNデリゲートチュートリアル(C#) から作業すると、次のようになります。

デリゲートが作成されると、関連付けられているメソッドは変更されないことに注意してください。デリゲートオブジェクトは不変です。

そして、コードサンプルでこれを確認します(コード全体を少し広げます)。

public delegate void ProcessBookDelegate(Book book);

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));

質問

ここで明らかに、ここでのコードの記述方法により、プロセスごとに新しいデリゲートが作成されます。私は推測不変性は、次のようなことをしようとする場合に関連しています

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);
ProcessBookDelegate thisIsATest = new ProcessBookDelegate(totaller.AddBookToTotal);

どちらが... thisIsATestが不変の場合でもコンパイルできますか?では、Microsoftを不変にすることでどのような問題を解決したのでしょうか。 C#6がデリゲートを変更可能にした場合、どのような問題が発生しますか?

[〜#〜]編集[〜#〜]

私は不変性がこれを防ぐと信じています:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);

thisIsATest.ChangeTheDelegateInABadFashion();

someFunction(thisIsATest); //This function works as normal
                           //because the delegate is unchanged
                           //due to immutability

しかし、不変性はこれを防止しません:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);

thisIsATest = new ProcessBookDelegate(ChangeTheDelegateInABadFashion());

someFunction(thisIsATest); //This function works weird now because
                           //it expected the unchanged delegate

この理解は正しいですか?

8
medivh

不変性の意味を混同していると思います。

不変性とは何か

この例を見てください:

_string s = "Hello";
s = "World";
_

stringsは不変ですか? はい
これはコンパイルされますか? はい
文字列インスタンスを何らかの方法で変更しましたか? いいえ

_"Hello"_には変更を加えていません。文字列を作成して変数sに割り当て、次にa newstringを作成し、変数sをこれで上書きします新しいstring。不変性はここでは役割を果たしません。

不変性とは

次のようなことを試してみると、

_s.MutateInSomeWay();
_

ここで、MutateInSomeWayは、文字列_"Hello"_(sの値)自体を変更するメソッドです。これは、文字列の不変性のために有効ではありません。

何らかの方法で変更するstringのメソッドは実際には変更せず、変更された値で新しいstringを作成し、呼び出し元に返します。

しかし、不変性はこれを防止しません:

_ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);  
thisIsATest = new ProcessBookDelegate(ChangeTheDelegateInABadFashion());
someFunction(thisIsATest); //This function works weird now because
//it expected the unchanged delegate
_

この理解は正しいですか?

はい、それは完全に有効であり、オブジェクトを変更していないため、不変性はそれを妨げません。もちろん、ChangeTheDelegateInABadFashion()が何であるかは完全に明確ではないため、具体的に説明するのは困難です。

15
Rotem

要するに理由:

  • 不変オブジェクトは、1つの状態、つまりオブジェクトが作成された状態(セキュリティ)にすることができます
  • スレッドセーフは自由に使用できますか
  • メモリの最適化
  • パフォーマンスが良い

詳細については、Stack Overflowで次の2つの質問を確認してください。

4
Manvik

標準のスレッドセーフティデリゲートが決して変更されないことがわかっている場合は、それについていくつかの仮定を行うことができます

特に、悪意のあるコードが、いくつかの関数に渡したデリゲートを(偶然であっても)変更できないことが保証されます。

これにより、バグの追跡が困難になり、プログラマがデリゲートが呼び出されなかった理由が不思議に思われる可能性があります。

2
ratchet freak