CLR 对不可变结构做什么?
我一直在阅读一些关于不可变结构的内容,例如字符串。简而言之,它们一旦创建就不会改变状态(例如,请求子字符串会给您一个新字符串)。
现在,我想知道 CLR 是否“知道”某种类型是不可变的,并利用这一事实在运行时做一些聪明的事情,或者不变性主要是使某些场景更易于编程?
I've been reading a bit about immutable structures such as string. Simply put, they don't change state once they've been created (so for instance asking for a substring gives you a new string).
Now, I was wondering whether the CLR "knows" that a certain type is immutable, and uses this fact to do something clever at runtime, or is immutability mainly something that makes certain scenarios simpler to program?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一般来说,CLR 不会对不可变类型做任何特殊的事情。它们的处理方式与任何其他类型相同。
对于字符串有特殊的支持。字符串可以被保留和重用。在 C# 中,源代码字符串文字由编译器自动保留。您还可以通过调用
String.Intern
。In general the CLR doesn't do anything special with immutable types. They are treated in the same way as any other types.
For strings there is special support. Strings can be interned and reused. In C#, source code string literals are automatically interned by the compiler. You can also intern a string yourself by calling
String.Intern
.编译器(而不是 CLR)有可能在生成 IL 时巧妙地利用它。我不知道它是否会,而且老实说我不在乎:如果它没有,也许将来会(以后的版本)。如果确实如此,也许将来就不会了(发现了一个边缘情况,表明优化是不明智的。
我很高兴地想“好吧,如果这是只读的,那么也许编译器(或者实际上, CLR)会用它做一些聪明的事情,所以这将是一个免费的改进”。这将是一个免费的改进,因为我永远不会做一些只读的事情来利用这样的优化,即使如果我知道它确实是这样做的,并且这样的节省是巨大的,那么我只会在只读有意义的情况下才会做一些事情,因为我的风格倾向于大量使用不可变对象,但我只会这样做。这是因为对象在逻辑上是不可变的,而不是为了追求某些优化而使其不可变,然后必须解决不可变性。
当然,您还可以通过某些方法巧妙地处理不可变对象(特别是在计算不同多线程场景对代码的影响时)。
Potentially, it could be possible for the compiler (rather than the CLR) to do something clever with it in producing IL. I don't know if it does, and honestly don't care: If it doesn't maybe it will in the future (later versions). If it does, maybe it won't in the future (an edge-case is found showing the optimisation to be ill-advised.
I'm happy to think "well, if this is readonly then maybe the compiler (or indeed, the CLR) will do something clever with it, so that'll be a free improvement". It'll be a free improvement because I'm never going to make something readonly to take advantage of such optimisations even if I learn that it definitely does so and that such savings are great. I will only ever make something readonly if it makes sense to be readonly. I do this a lot because my style favours heavy use of immutable objects, but I will only do it because the object is logically immutable, rather than make it immutable in pursuit of some optimisation and then have to workaround the immutability.
Of course, there are also certain ways that you can be clever with immutable objects (in particular, when working out the effects of different multi-threaded scenarios will have on your code).
从 CLR 的角度来看,该值是可变的。例如:CLR可以改变对象的数据来执行缓存。
该结构的用户无法更改其值,但 CLR 可以在多种情况下执行此操作。这就是 CLR 无法强制自身不变性并且无法在运行时依赖它的原因。
In the CLR's perspective the value IS MUTABLE. For example : the CLR can change the object's data to perform caching.
The users of the structure can't change it's value, but the CLR can do it in several scenarios. That's why the CLR can't enforce the immutability on itself and can't relay on it during the runtime.
编译器和 .net 都不会对不可变结构执行任何与可变结构不同的操作,尽管它确实对结构执行了一些操作,而这些结构只有在碰巧是不可变的情况下才在语义上有效。例如,如果将结构强制转换为 Object,则编译器将创建该结构的新装箱实例,并使用与原始数据相同的数据进行初始化。如果结构是可变的,则新实例在语义上将与原始实例不同,因为对一个实例的更改不会影响另一个实例。在其他一些情况下,编译器会复制结构并假装副本在语义上可以与原始版本互换;不幸的是,我不知道有什么方法可以请求会导致此类隐式复制的情况引发编译时错误,而不是让复制发生。
Neither the compiler nor .net does anything with immutable structures that it doesn't do with mutable ones, although it does do some things with structures which are semantically valid only if they happen to be immutable. For example, if a structure is cast to Object, the compiler will create a new boxed instance of the structure initialized with the same data as the original. If the structure is mutable, the new instance will not be semantically the same as the original, since changes to one instance will not affect the other. There are some other circumstances where compilers copy structures and pretend the copies are semantically interchangeable with the originals; unfortunately, I don't know any way to request that situations which would cause such implicit copies should raise a compile-time error rather than letting the copies happen.