.NET变得不可变

日期: 2013-01-20 来源:TechTarget中国 英文

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

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

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

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

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

  建造者和集合

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

  性能

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

.NET变得不可变

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

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐