BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

.NET变得不可变

| 作者 Jonathan Allen 关注 595 他的粉丝 ,译者 姚琪琳 关注 0 他的粉丝 发布于 2013年1月21日. 估计阅读时间: 3 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

.NET开发中一个常见的误区是,认为IEnumerable或ReadOnlyCollectionl类型的变量是线程安全的。微软的Andrew Arnott解释道:

如果有人给你一个ReadOnlyCollection<T>、IReadOnlyList<T>或IEnumerable<T>,唯一能保证的是你无法修改它们的数据,但却不能保证给你集合的人不会修改。不过对于数据不会改变这点,你往往需要一些信心。这些类型在改变内容时不会提供事件通知,并且如果在你迭代其内容的时候,集合真的改变了,这是否会发生在不同的线程呢?这种行为将造成应用程序中的数据崩溃和随机异常。

要在你想用IEnumerable或ReadOnlyCollection的地方提供真正线程安全的集合,微软BCL小组提供了一组不可变集合的预览版。基于函数式编程的技术,对于那些通常会改变集合的方法将会创建一个新集合来代替。为了提高效率,可能会在新旧集合之间进行数据共享。

不可变集合一个有意思的特点是没有公共构造函数。相反,它们总是以ImmutableXxx<T>.Empty作为开始。Andrew写到

使用静态Empty属性与传统模式相背离,但这么做是有原因的。构造函数必须要分配一个对象,但由于这些集合的不可变性,新的对象永远只能表示空的列表。鉴于修改集合会创建新的集合,因此使用构造函数会导致创建多个表示空列表的对象,这显然是种浪费。静态属性返回空列表的单例,应用程序中的所有代码都可以共享该单例。

建造者和集合

由于内存分配,构建一个不可变集合是相当昂贵的。我们已经在字符串(即字符的不可变集合)身上看到了这一点。为了缓解这一点,不可变集合将暴露一个ToBuilder方法,返回一个可以廉价修改的建造者对象。得到之后,还可以简单地使用ToImmutable再次得到不可变集合。

性能

不可变集合的性能可能会非常棘手。如下表所示,大多数不可变集合的时间复杂度都相当不错,并且是稳定的,不必担心在集合内部数组的最大尺寸会触发集合的完全拷贝。与普通集合不同,不可变集合中的项如果被移除,将会释放不用的空间。

但还是会有成本。每个操作都要在内存中分配另一个对象,给GC带来压力。最大的胜利是在创建集合的快照拷贝时。但最终的建议仍然是:使用最简单的代码完成工作,并在必要的时候调整性能。 该预览版可通过Microsoft.Bcl.Immutable NuGet包下载。

查看英文原文.NET Goes Immutable

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT