|
|
1
43
您可以创建一个类型,其中clr对其强制实施不可变。然后你可以用“不安全”来 关闭CLR强制机制 . 这就是为什么“不安全”被称为“不安全”的原因——因为它关闭了安全系统。在不安全的代码中,如果您足够努力,进程中的每个单字节内存都可以写。 包括不可变字节和clr中强制实现不可变的代码 . 您还可以使用反射来打破不变性。反射代码和不安全代码都要求授予极高的信任级别。
当然,使用不可变数据结构有很多原因。不可变的数据结构 岩石 . 使用不可变数据结构的一些好理由:
对于一个关于不可变类型的问题的答案永远保持不变的事实具有安全性的含义。假设您有这样的代码:
如果BAR是可变类型,则此处存在争用条件;BAR在另一线程上可能不安全。 之后 支票但 之前 危险的事情发生了。如果bar是不变的类型,那么问题的答案在整个过程中保持不变,这样更安全。(想象一下,如果可以改变包含路径的字符串 之后 安全检查但是 之前 例如,文件已打开。)
如果每个人都按规则行事,他们就是。如果有人使用不安全的代码或私有反射,那么 不再有规则执行 . 您必须相信,如果有人正在使用高特权代码,那么他们这样做是正确的,并且不会改变字符串。用你的能力运行不安全的代码只是为了好;有了强大的能力就有了巨大的责任。
这是个奇怪的问题。记住,锁是 合作的 . 只有当 每个人 访问特定对象与必须使用的锁定策略一致。 如果 商定 访问特定存储位置中特定对象的锁定策略是使用锁。如果这不是商定的锁定策略,那么使用锁是毫无意义的;当其他人在打开的后门中行走时,你小心地锁定和解锁前门。 如果您有一个字符串,您知道它正被不安全的代码所改变,并且您不希望看到不一致的部分突变,并且执行不安全突变的代码记录了它在该突变期间取出特定锁,那么是的,在访问该字符串时需要使用锁。但这种情况非常罕见;理想情况下,没有人会使用不安全的代码来操作其他线程上的其他代码可以访问的字符串,因为这样做是一个非常糟糕的主意。这就是为什么我们需要这样做的代码是完全可信的。这就是为什么我们要求这样一个函数的C源代码挥动一个大的红旗:“这个代码不安全,请仔细检查!” |
|
|
2
3
如果你变得不安全,也有可能改变C(IIRC)中的字符串。 |
|
|
3
3
没有完全不可变的类型,不可变的类是因为它不允许任何外部代码更改它。使用反射或不安全的代码仍然可以更改其值。
你可以使用
不可变类型有几个原因,比如性能和健壮性。
已知字符串是不可变的事实(在
从不可变类型创建的对象也可以在线程之间安全地传递。因为它们不能被更改,所以不同线程在同一时间更改它们是没有风险的,所以不需要同步访问它们。 不可变类型可以用来避免编码错误。如果你知道一个值不应该被改变,那么通常最好确保它不会被错误地改变。 |
|
4
2
这里没有黑魔法。字符串类是不可变的,因为它没有任何允许您修改内部字符串的公共字段、属性或方法。任何改变字符串的方法都会返回一个新的字符串实例。当然,你也可以用自己的课程来完成这项工作。 |
|
|
5
1
|
|
|
6
1
对。有一个构造函数来设置私有字段,只获取属性,不获取方法。
一个例子:这样的类型不需要从多个并发线程安全地使用锁,这使得正确的代码更容易编写(没有错误的锁)。 附加:总是有可能有足够的特权代码绕过.NET保护:要么反射到私有字段读写,要么不安全的代码直接操作对象的内存。 这在.NET之外是正确的,特权进程(即具有进程或具有“上帝”特权的线程令牌,例如启用所有权)可以闯入任何其他进程加载DLL、注入运行任意代码的线程、读或写内存(包括覆盖执行保护等)。系统的完整性只有在系统所有者的合作下才能得到加强。 |
|
|
Fishie · 作为类成员的智能指针是否仍然自动释放?[关闭] 1 年前 |
|
|
Anka Hanım · 关于结构和动态数组地址的问题 1 年前 |
|
|
tTt · 使用堆栈中的值重新分配指针 1 年前 |
|
|
manuel · 现代C中空指针的替代方案++ 1 年前 |