【问题标题】:Is there any disadvantage to returning this instead of void?返回 this 而不是 void 有什么缺点吗?
【发布时间】:2008-09-11 17:32:51
【问题描述】:

假设你返回一个类的引用而不是返回一个方法,即使它没有任何特定的语义意义。在我看来,它会给你更多关于如何调用方法的选择,允许你以类似流畅的界面风格使用它,我真的想不出任何缺点,因为你不需要做任何事情带有返回值(甚至存储它)。

假设您处于想要更新对象然后返回其当前值的情况。 而不是说

myObj.Update();
var val = myObj.GetCurrentValue();

你可以把这两行结合起来说

var val = myObj.Update().GetCurrentValue();

编辑:我一时兴起问了以下问题,回想起来,我同意这可能是不必要且复杂的,但是我的问题是关于返回这个而不是 void 立场。

在相关的说明中,你们如何看待让该语言包含一些新的语法糖:

var val = myObj.Update()<.GetCurrentValue();

此运算符的优先级较低,因此 myObj.Update() 将首先执行,然后在 myObj 上调用 GetCurrentValue(),而不是 Update 的 void 返回。

基本上我在想象一个运算符,它会说“在左侧第一个有效对象上调用运算符右侧的方法”。有什么想法吗?

【问题讨论】:

    标签: .net fluent-interface


    【解决方案1】:

    我认为作为一般政策,它根本没有意义。以这种方式链接的方法适用于正确定义的接口,但只有在语义上有意义时才适用。

    你的例子是不合适的,因为它没有语义意义。

    同样,如果设计得当的流畅界面,您的语法糖也不必要。

    Fluent 接口或方法链可以很好地工作,但需要仔细设计。

    【讨论】:

    • 方法链的一个优点是它可以避免使用定义局部变量,这(如果不推得太远)是一个好习惯。
    【解决方案2】:

    我知道在 Java 中他们实际上正在考虑为 void 方法制定这种标准行为。如果你这样做,你就不需要额外的语法糖。

    我能想到的唯一缺点是性能。但这很容易衡量。我会在几分钟后回复你结果:-)

    编辑:

    返回引用比返回 void 慢一点。真是令人惊讶。所以这是唯一的缺点。调用你的函数时再敲几下。

    【讨论】:

    • smalltalk ftw,虽然你不能在其中很好地进行方法链接
    【解决方案3】:

    我能看到的唯一缺点是它使 API 更加混乱。假设您有一些带有 remove() 方法的集合对象,该方法通常会返回 void。现在您要返回对集合本身的引用。新签名如下所示:

    public MyCollection remove(Object someElement)
    

    仅查看签名,并不清楚您返回的是对同一实例的引用。也许 MyCollection 是不可变的,而您正在返回一个新实例。在某些情况下,例如这里,您需要一些外部文档来澄清这一点。

    我实际上喜欢这个想法,并且我相信在 Java7 中改进所有 void 方法以返回对“this”的引用,但它最终失败了。

    【讨论】:

    • 没错,但它也允许您编写简化的代码,例如 myCollection.remove(item1).add(item2).swap(item3, item4)
    【解决方案4】:

    “流畅的接口”——就像 JQuery 使用的那些——不就是这样构建的吗?一个好处应该是代码可读性(尽管http://en.wikipedia.org/wiki/Fluent_interface 的维基百科条目提到有些人认为它可读)。另一个好处是代码简洁,您无需在 7 行代码中设置属性,然后在第 8 行调用该对象的方法。

    Martin Fowler(他在这里创造了这个术语 - http://martinfowler.com/bliki/FluentInterface.html)说,流式接口比方法链更多,但是方法链是用于流式接口的常用技术。

    编辑: 我实际上是回到这里来编辑我的答案并补充说,当我看到乔治的评论指出我确实忘记讨论 point的问题。很抱歉最初的“毫无意义”漫无边际。

    【讨论】:

    • 是的,这就是为什么我提到这是流畅的界面风格,正如你所说,流畅的界面不仅仅是方法链接。问题是这是否真的有任何缺点
    【解决方案5】:

    返回“self”或“this”是一种常见模式,有时称为"method chaining"。至于您提出的语法糖,我不太确定。我不是 .NET 人,但它对我来说似乎不是非常有用。

    【讨论】:

    • 是的,也许不是运营商的想法,但我仍然很好奇在此返回 void 可能有什么好处
    【解决方案6】:

    NeXTSTEP Objective-C 框架曾经使用过这种模式。一旦分布式对象(基本上是远程过程调用)被添加到语言中,它在该框架中就停止了——返回 self 的函数必须是同步调用,因为分布式对象系统看到返回类型并假设调用者需要知道函数的结果。

    【讨论】:

    • 我知道这将是一个问题,尽管这不是 C# 或 VB 代码的限制。
    • 嗯,理论上它可能是任何支持自省的语言的问题。
    【解决方案7】:

    乍一看,它可能看起来不错,但要获得一致的接口,您需要所有方法都返回对 this 的引用(这有其自身的问题)。

    假设你有一个类有两个方法 GetA 返回 this 和 GetB 返回另一个对象:

    那你可以调用obj.GetA().GetB(),但不能调用obj.GetB().GetA(),至少看起来不一致。

    使用 Pascal(和 Visual Basic),您可以调用同一对象的多个方法。

    with obj
      .GetA();
      .GetB();
    end with;
    

    此功能的问题在于,您可以轻松编写比应有的更难理解的代码。另外添加一个新的运算符可能会变得更难。

    【讨论】:

    • 好吧,如果 GetA() 方法一开始就返回 void,那就太奇怪了。一个更合理的例子是 obj.UpdateA().GetA() 这对我来说非常有意义
    • 一个问题 - obj.GetA() 返回 A 而不是这个更有意义吗?我们不是在牺牲可读性吗?
    • 您对示例的阅读过多。 'this' 可能是 'A*' 类型,因此 'GetA' 返回 '*this' 非常有意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 2012-07-01
    • 2017-10-13
    • 2014-04-10
    相关资源
    最近更新 更多