“流利”(或可链接)方法必须是不可变的吗?

时间:2011-07-15 09:33:32

标签: c# fluent fluent-interface

假设我有一个带有一些属性的类和一些操作这些属性的方法:

public class PersonModel
{
    public string Name { get; set; }
    public string PrimaryPhoneNumber { get; set; }

    public void LoadAccountInfo(AccountInfo accountInfo)
    {
        this.Name = accountInfo.Name;
    }

    public void LoadPhoneInfo(PhoneInfo phoneInfo)
    {
        this.PrimaryPhoneNumber = phoneInfo.PhoneNumber;
    }
}

典型用法是:

var model = new PersonModel();
model.LoadAccountInfo(accountInfo);
model.LoadPhoneInfo(phoneInfo);

我认为将方法链接起来会很酷:

    public PersonModel LoadAccountInfo(AccountInfo accountInfo)
    {
        this.Name = accountInfo.Name;
        return this;
    }

    public PersonModel LoadPhoneInfo(PhoneInfo phoneInfo)
    {
        this.PrimaryPhoneNumber = phoneInfo.PhoneNumber;
        return this;
    }

然后用法是:

var model = new PersonModel()
    .LoadAccountInfo(accountInfo)
    .LoadPhoneInfo(phoneInfo);

但是我没有在这些可链接的方法中返回传入的PersonModel对象的修改“克隆”。他们只是修改原始对象并返回它(为方便起见)。对我来说,这会造成歧义,因为有人调用这些方法可能会认为它们是不可变的(即它们保持原始对象不变但返回修改后的对象)。

这是否违反了关于流利/可链接接口的任何最佳做法?

5 个答案:

答案 0 :(得分:4)

不,改变传递的对象是完全合理的。流畅的NHibernate方法都以这种方式工作(例如,当他们修改FluentConfiguration对象时)。

但它也不是一个规则。 String是不可变对象的最佳示例,您可以在其中链接一组方法,每个方法都返回一个新实例。

答案 1 :(得分:3)

就我个人而言,我认为不变性和流畅的界面是一个单独的问题。一般来说,你可能会发现不变性是一件好事,一种最佳做法。但这就是你是否使用了流畅的界面。

答案 2 :(得分:1)

流畅方法的所有魅力在于返回相同的修改对象。

答案 3 :(得分:1)

本文建议对象应该是不可变的。它来自功能语言的角度。

http://blogs.msdn.com/b/laurionb/archive/2009/02/16/immutable-objects-in-fluent-interfaces-a-lesson-from-functional-programming.aspx

但是,以Moq为例,对象不是一成不变的。

我认为这里没有“最佳实践”。正如@Ray Toal所说,他们是一个单独的问题。

答案 4 :(得分:0)

对象是引用类型,当你特别要求它“返回”时,为什么你会期望它返回不同的东西。

不违反任何最佳做法。事实上,除非你有理由不需要克隆一个对象。