不可变对象比静态方法有什么优势?

时间:2009-09-29 23:48:03

标签: immutability static-methods

interface IDependency
{
    string Baz { get; set; }
}

class Foo
{
    IDependency dependency;

    public Foo(IDependency dependency)
    {
        this.dependency = dependency;
    }

    public void FubarBaz()
    {
        dependency.Baz = "fubar";
    }
}

我也可以将其实现为:

class FooStatic
{
    public static void FubarBaz(IDependency dependency)
    {
        dependency.Baz = "fubar";
    }
}

什么时候应该选择不可变对象而不是静态方法?是否存在相反的情况?

另外,在我看来,不可变对象不应该有void方法。你觉得怎么样?

2 个答案:

答案 0 :(得分:3)

不可变对象当然可以有void方法 - 除了改变对象的状态之外还有其他类型的副作用。考虑:

public void WriteTo(Stream stream)

作为一个例子。

至于你的“不可变对象与静态方法”问题 - 如果你的方法实际上需要Foo状态的几个方面怎么办?仅仅因为状态没有改变并不意味着将该状态封装在一起是没有意义的。假设它有5个依赖项而不是1个 - 你想写很多带有5个参数的静态方法吗?当你获得第六个依赖(或者甚至只是另一个状态)时,你真的想要将第六个参数添加到所有方法中,还是只添加到构造函数中?

答案 1 :(得分:0)

FubarBaz()会改变成员Foo.dependency,因此Foo不是不可变的。不变性是一种设计约束,可以而且应该通过标记字段readonly在C#中更好地表达。你的依赖的连接可以而且应该在构造函数中完成(如果你正在做IoC,大多数框架都需要这个)。不可变的设计最终会像这样:

class Foo
{
    private readonly IDependency dependency;

    public Foo(IDependency dependency)
    {
        this.dependency = dependency;
        dependency.Baz = "fubar";
    }
}

可变和不可变类设计都有时间和地点。也许一个值经常变化而且这个类没有被共享,那么一个可变类可以工作。不变性具有不变性的优点。您可以传递对该对象的引用,并确保它指向的值永远不会更改。这是一个强大的概念,尤其是在处理多线程应用程序时。

使用静态类的决定应该基于您希望调用的方式,或者您是否绝对需要使用静态,例如创建扩展方法时的情况。 IME,在实现调用之前编写调用是在连接实现之前决定设计的好方法。静态基本上与非静态相同,除了静态不能“新起来”(由你构造)。静态不是不可变的,特别是因为你没有构造它们。你只需要处理一个实例。

我认为没有理由避免在不可变类设计中的方法上使用void返回类型。