首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么是不变性,我为什么要担心它?

什么是不变性,我为什么要担心它?
EN

Stack Overflow用户
提问于 2009-03-07 22:50:06
回答 9查看 9.5K关注 0票数 59

我已经读了几篇关于不变性的文章,但仍然没有很好地理解这个概念。

我最近在这里做了一个提到不变性的帖子,但由于这本身就是一个主题,我现在正在制作一个专门的帖子。

我在过去的帖子中提到过,我认为不变性是将对象设为只读并使其具有低可见性的过程。另一位成员表示,这与此没有任何关系。This page (series的一部分)使用了一个不可变的类/结构的例子,它使用只读和其他概念来锁定它。

在本例中,状态的定义到底是什么?状态是一个我还没有真正掌握的概念。

从设计指南的角度来看,不可变的类必须是不接受用户输入并且真正只返回值的类。

我的理解是,任何只返回信息的对象都应该是不可变的和“锁定的”,对吧?因此,如果我想用那个方法在专用类中返回当前时间,我应该使用引用类型,因为这将是该类型的引用,因此我受益于不变性。

EN

Stack Overflow用户

发布于 2009-03-08 04:48:35

您不能更改不可变对象,因此必须替换它...“去改变它”。即先替换后丢弃。“替换”在这个意义上意味着将指针从一个内存位置(旧值)更改到另一个内存位置(新值)。

请注意,在这样做的过程中,我们现在使用了额外的内存。一些用于旧值,一些用于新值。还请注意,有些人会感到困惑,因为他们看代码,例如:

代码语言:javascript
运行
复制
string mystring = "inital value";
mystring = "new value";
System.Console.WriteLine(mystring); // Outputs "new value";

然后对自己说:“但是我正在改变它,就在那里,黑白分明的!我的字符串输出‘新值’……我记得你说过我不能改变它?!!”

但实际上在幕后,发生的是这种新内存的分配,即mystring现在指向不同的内存地址和空间。“不可变”在这个意义上并不是指mystring的值,而是指变量mystring用来存储其值的内存。

在某些语言中,存储旧值的内存必须手动清除,即程序员必须显式地释放它。记住要这么做。在其他语言中,这是该语言的一个自动特性,即.Net中的垃圾收集。

这真的让re大吃一惊:内存使用是在高度迭代的循环中,特别是在Ashs的post中使用字符串。假设您在一个迭代循环中构建一个HTML页面,您不断地将下一个HTML块追加到最后一个块中,并且为了好玩,您是在一台高容量服务器上这样做的。如果“旧值内存”没有得到适当的清理,这种“新值内存”的持续分配很快就会变得昂贵,并最终致命。

另一个问题是,有些人认为像垃圾收集(GC)这样的事情会立即发生。但事实并非如此。有各种优化措施,使得垃圾收集被设置为在更多的空闲时间内进行。因此,在内存被标记为已丢弃的时间和垃圾收集器实际释放内存的时间之间可能会有明显的延迟。因此,如果您只是将问题推迟到GC,那么您可能会遇到大量的内存使用高峰。

如果GC在内存耗尽之前没有机会进行操作,那么事情就不一定会像其他没有自动垃圾回收的语言那样崩溃。取而代之的是,GC将作为最高优先级的进程来释放被丢弃的内存,无论时间有多糟糕,并且在它清理东西的过程中成为一个阻塞进程。显然,这并不酷。

因此,基本上,您需要在编写代码时牢记这些事情,并查看您正在使用的语言的文档,以获得最佳实践/模式,以避免/减轻这种风险。

在Ashs的帖子中,在.Net和字符串中,当涉及到需要不断更改字符串值时,推荐的做法是使用可变的StringBuilder类,而不是不可变的string类。

其他语言/类型也同样有自己的变通方法。

票数 1
EN
查看全部 9 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/622664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档