5

我最近开始阅读 C# 中的可变和不可变对象,我发现无论我在哪里读到的不变的东西是帽子是不可变的,这使得当用作哈希表中的键时线程安全且有用,但我不明白就概念而言虽然我们无法更改内容,但我们可以更改参考:

string s = "Hi";
s = "Bye";

虽然这里 s 的引用更改为“Bye”,但主要是 s 的内容(或者更确切地说它指向的内容)已经改变,并且从编程的角度来看是相同的,那么这是怎么回事如果字符串更改,则使特定函数线程安全或在哈希表中可用??

4

2 回答 2

2

简单的。如果您要传递给在不同线程上运行的代码,则此代码将接收传递参数时s指向的字符串。s像 .net 中的所有字符串一样,它不会随着时间而改变,因此您的线程代码不需要考虑您可能会重新分配s给不同的值。

如果您将“再见”分配给s,则原始字符串将继续存在(直到其垃圾被收集),并且您的变量s指向一个新字符串。

在字典中,略有不同。如果您更改可变键以使其哈希码发生变化,则字典将无法找到该键:哈希码用于在索引中搜索,如果哈希码随时间变化,字典将找不到正确的记录。所以这并不真正需要不变性,但不变性将确保哈希码的一致计算。

不变性对您的作用是它使您能够将对象视为一种值类型(例如 int),这通常更容易推理。

于 2013-09-29T16:53:48.110 回答
0

在您的示例中,s重新分配以引用不同的string对象(“Bye”),但s之前引用的对象(“Hi”)没有改变。任何其他引用字符串“Hi”(另一个线程、aDictionary等)的内容都不会受到影响。正如您所提到的,string它是不可变的 - 它的内容一旦创建就无法更改。例如,如果您将一个附加string到另一个,您将获得一个新string对象。两个原始string对象保持不变。这就是string线程安全的原因,并且适合在哈希表中使用。

引用s 不是线程安全的 - 为了确保使用引用时的线程安全,您需要在引用分配周围加一个锁,以确保一个线程在另一个线程正在写入时不会尝试从引用中读取它。

于 2013-09-29T16:46:56.393 回答