不可变性对非并行应用程序有用吗?

时间:2009-06-22 21:56:54

标签: c# .net performance immutability

我喜欢不变性概念,但有时我想知道,当一个应用程序不是平行的时候,应该避免让事情变得不可变吗?

当应用程序不是多线程的时,您不会受到共享状态问题的困扰,对吧?

或者不可变性是像OOP这样的概念,你要么一直使用?排除基于使用/性能等因素不应该是不可变的情况

在为自己编写应用程序时,我遇到了这个问题,这个问题适度大(可能像1-2k行)。

3 个答案:

答案 0 :(得分:9)

我喜欢不可变性的优势,只需要在创建对象时验证它一次。实际上这是一个巨大的奖金。

答案 1 :(得分:8)

我喜欢不变性,因为这意味着我不必相信其他人的代码,不要乱用我希望保持不变的对象。

当您将一个对象传递给另一个组件(例如List<T>)时,您将受到该组件的作用。将集合作为属性返回时,这一点尤其重要。

public class Foo { 
  private List<Bar> _barList;
  public ICollection<Bar> BarList { get return _barList; } 
}

没有什么可以阻止这个类的消费者清除我下面的收藏品。即使将返回类型切换为IEnumerable<Bar>也不完全安全。什么都没有阻止一些编写得不好的代码将其转回List<T>并调用.Clear()。

但是,如果我真的希望该集合保持一致,我可以将其重写为followis

public class Foo {
  private ImmutableCollection<Bar> _barList;
  public ImmutableCollection<Bar> BarList { get { return _barList; } }
}

现在我不必信任其他代码错误地使用我的类。他们不能弄乱它。

答案 2 :(得分:2)

不变性的一个主要好处是不需要跟踪不可变对象的所有权。只要有人需要它们,它们就存在,然后当它们不再需要时就消失在虚无之中。虽然在许多情况下使用垃圾收集器意味着没有必要编写处理可变对象所有权的任何明确代码(最大的例外是实现IDisposable的那些),在许多情况下,编写正确的代码非常困难。哪些具有可变状态的对象没有一个明确定义的“所有者”。关于谁拥有可变对象状态的困惑可能是一个非常频繁的错误来源;当使用不可变对象(除了少数实现IDisposable)之外,通常可以忽略所有权问题。

另一个需要考虑的问题是,推断对语义不可变对象的可变引用或对可变对象的不可变引用要比推断对可变对象的可变引用要容易得多。如果有一个可变对象的可变引用,通常不清楚更新状态的正确方法是直接改变对象,还是将其状态复制到新对象,改变它,并更新引用。在某些情况下,会出现需要每种类型操作的情况(与List<T>一样,有时会替换一个更大的数组,但通常会进行就地更新),但这种方法只适用于类型保持对有问题的可变对象的独占控制。对可变类型进行不可变引用(在这种情况下,代码可能通过只读包装器将引用公开给需要其状态的“实时视图”的其他对象)通常更有帮助,或者有一个对引用不可变的对象的可变引用,或者至少在引用的生命周期内永远不会发生变异。