背景
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
この理解は正しいですか?
不変性の意味を混同していると思います。
この例を見てください:
_string s = "Hello";
s = "World";
_
string
sは不変ですか? はい
これはコンパイルされますか? はい
文字列インスタンスを何らかの方法で変更しましたか? いいえ。
_"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()
が何であるかは完全に明確ではないため、具体的に説明するのは困難です。
要するに理由:
詳細については、Stack Overflowで次の2つの質問を確認してください。
標準のスレッドセーフティデリゲートが決して変更されないことがわかっている場合は、それについていくつかの仮定を行うことができます
特に、悪意のあるコードが、いくつかの関数に渡したデリゲートを(偶然であっても)変更できないことが保証されます。
これにより、バグの追跡が困難になり、プログラマがデリゲートが呼び出されなかった理由が不思議に思われる可能性があります。