C# 只读结构在数组中是否应该是不可变的?

C# 只读结构在数组中是否应该是不可变的?,c#,immutability,c#-7.2,system.memory,C#,Immutability,C# 7.2,System.memory,(注意:此示例代码需要C#7.2或更高版本以及软件包。) 假设我们有一个只读结构,如下所示: public readonly struct Test { public Test(int value) { Value = value; } public int Value { get; } } 现在让我们将其放入一个数组: var array = new Test[] { new Test(1) }; Console.WriteLine(arr

(注意:此示例代码需要C#7.2或更高版本以及软件包。)

假设我们有一个
只读结构
,如下所示:

public readonly struct Test
{
    public Test(int value)
    {
        Value = value;
    }

    public int Value { get; }
}
现在让我们将其放入一个数组:

var array = new Test[] { new Test(1) };

Console.WriteLine(array[0].Value); // Prints 1
到目前为止还不错。无法编写代码来直接修改数组[0]。值

现在假设我们这样做:

array.AsSpan().AsBytes()[3] = 1;

Console.WriteLine(array[0].Value); // Prints 16777217
现在我们修改了数组中readonly结构的
组件

这种行为正确吗

这种行为正确吗

对。只读结构不会改变保存结构副本的变量的易变性!数组元素是变量,变量可以变化

您不需要使用C#7.2来查看这一点。整数是不可变的;无法将整数3转换为整数4。而是将包含3的变量的内容替换为4。整数是不可变的事实并不能使变量变成常数。彼此彼此。结构是不可变的,就像int一样,但是包含它的变量是可变的

类似地,结构上的只读字段也是谎言;可以观察到该字段发生了更改,因为结构不拥有其存储。请参阅以了解更多关于此的信息


(当然,如果您在高信任级别或不安全的代码中使用反射来违反语言和运行时的规则,那么一切都是可变的。)

@将无法确定它是否真的是一个bug,这就是我提出问题的原因。这可能是意料之中的行为!无法编写代码来直接修改数组[0]。值。我想就这些了。你不能用反射来修改它吗?Span在本例中似乎只是另一种间接的方法。@downvoter:指出您认为这个问题有什么问题是很有帮助的,这样它就可以得到改进。如果我们试图谈论不变性,或者在没有像“完全克隆”这样的极端开销的情况下保护数据不受意外修改,那么C#完全是一个垃圾。C#架构师完全忽略了这个概念,这让我感到非常难过。要用新值替换变量的内容,首先应该能够以某种方式获得新值。如果结构构造函数对它将创建的值有一些限制:
public readonly struct DivisibleBy256{public DivisibleBy256(int-value){value=value&~255;}public int-value{get;}}
,将
.AsSpan().AsBytes()
遵守这些限制吗?@PetSerAl:Nope。将字节直接写入内存是最危险的事情之一。如果你不喜欢这样做,那么我的建议是:不要这样做。我主要关心的是:如何防止别人这样做。但仔细观察,似乎整个
系统.Memory
程序集隐式地
SecurityCritical
,因为没有任何程序集级别的安全属性,因此它不能从部分受信任的代码中调用。@PetSerAl:C#只是大部分内存安全和类型安全。核心语言非常擅长使绝大多数程序员永远不会违反安全性,但是如果他们真的想这样做的话,完全可信的代码有很多机会这样做;这只是多一个。