class string
是不可变的。不可能实现不可变的结构类型,因为您无法禁用或覆盖赋值操作(=
)。即使您定义了只读结构,您也始终可以使用赋值运算符更改结构类型的值。
例如,
x,y
是只读结构体的值。 x = y;
将更改x
的内容。因此,C# 语言参考中的只读结构部分不正确。这是正确的吗?
我在维基百科上找到了一个部分可以解释你的问题:
违反不变性
不变性并不意味着对象存储在 计算机的内存是不可写的。相反,不变性是 编译时构造,指示程序员可以通过以下方式执行哪些操作 对象的正常接口,不一定是它们可以的 绝对可以(例如,通过绕过类型系统或 违反了 C 或 C++ 中 const 的正确性)。
用我自己的话说,“不可变”和“赋值”是 C# 作为编程语言中的两个独立的概念。 “不可变”只是指对象状态的不变性。您认为值类型可以通过重新分配而可变的原因是因为值类型的分配恰好覆盖了它们分配的内存。正如 wiki 上所述,如果有一种方法可以写入字符串引用的内存,它也会违反其不变性。 (这确实是可能)
不,你错了。
readonly struct
上的文档完全正确。您的问题包含一个损坏的链接(您已在评论中修复它,但最好修改问题),此文档页面和部分的正确 URL 是 this。
解释非常简单。考虑这个例子:
readonly struct A {
internal A(int first, string second) { First = first; Second = second; }
internal readonly int First { get; init; }
internal readonly string Second { get; init; }
}
static class ReadonlyUsage {
static A value = new(0, "original value");
internal static void Demo() {
A a = new(1, "constant value");
//a.First = 12; // will fail to compile
a = new(2, "another value");
// this is mutable:
value = new(3, "one more value");
//value.First = 13; // will fail to compile
// still mutable:
value = new(4, "How much longer?!");
}
}
这里什么是可变的?除了
ReadonlyUsage.value
之外什么都没有,它使得 ReadonlyUsage
也可变。它与 struct A
无关——它是不可变的。完全一样System.String
。
让我们看看:分配给
A a
怎么样?此赋值是否会使 ReadonlyUsage
可变?不会。您将新值(struct A
是值类型)分配给堆栈变量。它仅存在于堆栈中,并且在当前堆栈帧退出后将被删除。堆栈不属于类,它属于调用ReadonlyUsage.Demo
的线程。如果它是 实例类,则该赋值不会修改
Demo
类中的任何内容。我们只需创建一个新的 struct A
实例,并且从不修改任何已经存在的实例,这就是它被称为不可变的原因。
现在,给
ReadonlyUsage.value
的分配怎么样?这是可能的,因为 ReadonlyUsage
是可变的。同样,我们创建 struct A
的新实例,并且永远不会修改任何已存在的实例。
如何防止分配给
ReadonlyUsage.value
?简单:也做到readonly
:
static readonly A value = new(0, "original value");
就是这样。我希望误会能够消除。那么你会接受这个答案吗?如果没有,请进一步提问。