【问题标题】:What is the correct way to chain methods in .Net在.Net中链接方法的正确方法是什么
【发布时间】:2011-07-14 01:30:00
【问题描述】:

在 .Net 中,您可以链接返回值的方法或使用 void。其中之一是“正确的方式”吗?

所以你可以说

1)

Foo myFoo = new Foo();
myfoo.Bars = 
  myBars.DoSomethingCool(x)
  .DoSomethingElse(y)
  .AndSomethingElse(z);

public static IList<IBar> DoSomethingCool(this IList<IBar> source, object x)
{
  IList<IBar> result = //some fn(source)
  return result;
}

在这种情况下,所有 3 个扩展方法都需要返回 IList(myFoo.Bars 的类型)

也可以写成

2)

myBars.DoSomethingCool(x)
.DoSomethingElse(y)
.AndSomethingElse(z);

public static void DoSomethingCool(this IList<IBar> source, object x)
{
  //Modify source
  source = //some fn(source)
  //Don't return anything
}

在这种情况下,扩展方法返回一个 void,但对传入的源对象执行工作?

更新 Simon 的回答是正确的,即 2) 不会编译。以下是可以重写的方法:

DoSomethingCool(myBars)
.DoSomethingElse(myBars)
.AndSomethingElse(myBars);

myBars 然后会在每个方法的调用中发生变化,并且这些方法将返回 void。

【问题讨论】:

  • 链接方法使代码更难调试、修改和维护。
  • 我不确定我是否理解它如何使调试、修改和维护变得更加困难。如果将链接放在单独的行上,则可以在任何语句处设置断点。链接使表达意图更容易,在我看来,这使维护更容易,而不是更难。
  • 您的第二个示例无法编译。在 DoSomethingCool 的返回结果上调用 DoSomethingElse(),这是一个 void。
  • 链接很糟糕,因为您不能单步执行每个逻辑代码行……要么全有,要么全无。您不能在步骤上设置断点。如果一个步骤失败,你不知道它是哪一步。将所有代码放在一行中会使眼睛更难以解析单独的步骤。为了说明,将程序中的每一步都放在一行上。你喜欢它吗?将每个逻辑步骤放在一行上会好得多。
  • 西蒙,你是对的。我必须返回一个类型,否则我只能将结果链接一次。

标签: .net extension-methods method-chaining


【解决方案1】:

在这两种情况下,您都在使用扩展方法,返回一个对象,然后将该对象用作链中下一个方法的输入。第二个例子接近Fluent Interface(但不完全是)。我认为在你的两个例子中,关键区别是可变性之一。您希望修改原始输入(第二个示例)还是不修改(第一个示例)? “正确”的答案取决于情况和上下文。

【讨论】:

  • 问题来了:修改原始输入是否可以,或者通过副作用进行操作是一件坏事?
  • 我不知道以这种方式通过扩展方法进行修改一定是“坏事”,尽管我个人可能会远离它以避免混淆 - 至少我会命名改变带有“更改...”或“修改...”之类的对象。按照惯例,几乎所有的 Linq 扩展方法都在迭代器上运行并提供新序列,而不是修改原始序列。通过操作并返回最小公分母(迭代器),Linq 扩展可以适应最广泛的情况和目标对象。
  • 要记住的一点是,扩展方法实际上与任何其他方法没有什么不同,第一个参数只是隐式而不是显式的。这意味着因为它在被操作的对象的外部,所以该方法不能比任何其他方法拥有更多的访问权限。如果原始对象不可变,则链中的方法也不能改变它。这意味着只要原始对象的接口设计得当,您就不会面临通过任何一种方法破坏封装的危险。
【解决方案2】:

1) 获胜。西蒙正确地回答了 2) 不会编译,但他是作为评论这样做的,所以我不能把他的回答归功于他。 2) 的更新解决方案将所有事情都作为副作用,我想不出为什么你会想要在静态类型语言中这样做。

关于链式调试问题的观点值得考虑,尽管我发现链式在过滤时特别有用。

mybars.FilterByHasHappyHour()

好很多
BigGiantUtilityClass.GetBarsWithHappyHours(myBars)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多