【问题标题】:Is there any point in using local functions if to only use them once?如果只使用一次,使用局部函数有什么意义吗?
【发布时间】:2018-05-20 19:19:13
【问题描述】:

想象一下我有这个代码:

public void Foo()
{
    // Do bar work
    // Do baz work
    // Do foobar work
}

我意识到我可以(并且应该因为它做不止一件事)将其重构为:

public void Foo()
{
    bar();
    baz();
    foobar();
}

private void bar()    { /* do bar work */ }
private void baz()    { /* do baz work */ }
private void foobar() { /* do foobar work */ }

但后来我意识到我永远不会在Foo() 之外使用这些功能,所以这些功能只会使主页和自动完成功能变得混乱。我可以摆脱这个:

public void Foo()
{
    bar();
    baz();
    foobar();

    void bar()    { /* do bar work */ }
    void baz()    { /* do baz work */ }
    void foobar() { /* do foobar work */ }
}

这会让事情变得更整洁、更简洁,但我现在真正所做的只是让方法变得更长而不是更短。

【问题讨论】:

  • 它可以帮助您提高可读性和可维护性,但这取决于方法。它们包含大量代码还是只有几行代码?
  • 我想这归结为可读性。如果留在主函数上,bar()、baz() 和 foobar() 会吐出多少代码。此外,它们的相关性是否足以成为主要的
  • 如果代码组织是唯一的问题,只需将它们自己粘贴到部分类文件中即可。此外,您可以命名私有帮助方法,这样它们就不会直接跳到自动完成的顶部。
  • @SebastianHofmann 有问题的方法只有11行
  • 您的本地函数版本看起来还不错,它将事物保持在最小的必要范围内,同时仍将(我猜)有用的名称放入代码块中。

标签: c# methods refactoring local c#-7.0


【解决方案1】:

这会让事情变得更整洁,更简洁,但我现在真正所做的只是让方法变得更长而不是更短。

不,你没有。您基本上是在说类似的东西,一个类具有一个执行大量工作的方法与一个执行相同工作但具有多个更短且更易于维护的方法的类之间没有任何区别。

您的本地函数就像方法一样,它们包含在另一个方法中这一事实并不排除整体更容易维护;功能被封装在明确定义的范围内。

【讨论】:

    【解决方案2】:

    我很喜欢@Mark Benningfield 使用部分文件的想法(当我的课程太大并且有一两个超级方法时,我会这样做)

    我对局部函数的唯一问题是它们可以捕获变量,并且并不总是很清楚它们是否正在这样做。因此,通过将“真实”方法“推广”到“本地”,您正在扩大它的知名度。

    【讨论】:

    • 对,但有时捕获变量是我想要的行为。我确实喜欢本地函数能够直接使用父函数的参数或局部变量,而不必将它们作为参数传递。
    • @AustinWBryan 捕获变量没有问题......只是我更喜欢本地函数使用这个特性,其他函数显然没有。所以我用这个(捕获/不捕获)作为分界线。但这是在沙子上画的线。
    • 我明白了,这是一个聪明的经验法则
    【解决方案3】:

    本地函数比匿名函数更有优势,因为匿名函数只能通过委托调用,除了为委托分配内存之外,调用成本更高。

    本地函数可以递归,而无需委托所需的技巧:

    int f(int i) => i >= 1 ? i * f(i - 1) : 1;
    
    Func<int,int> d = null;
    d = (int i) => i >= 1 ? i * d(i - 1) : 1;
    

    与匿名委托一样,与顶级方法不同,局部函数可以捕获局部变量。而且因为 thy 是本地的,所以它们不能被其他函数调用。

    【讨论】:

      【解决方案4】:

      使用匿名函数:

      public void Foo()
      {
          Action bar = delegate () { /* do bar work */ };
          Action baz = delegate () { /* do baz work */ };
          Action foobar = delegate () { /* do foobar work */ };
      
          bar();
          baz();
          foobar();
      }
      

      或 lambda 表达式语法:

      public void Foo()
      {
          Action bar = () => { /* do bar work */ };
          Action baz = () => { /* do baz work */ };
          Action foobar = () => { /* do foobar work */ };
      
          bar();
          baz();
          foobar();
      }
      

      【讨论】:

      • 这个比问题中显示的版本没有优势,缺点是更长。
      • 这实际上是一回事,除了我必须在代码之上声明匿名函数这一事实。我喜欢在所有东西下都有本地函数,包括返回语句。我觉得它更容易阅读。
      • 另外,使用委托会产生性能成本,因为它必须分配内存来创建委托,但如果我不打算将该委托传递给其他东西(我不打算)那就是浪费内存。本地函数不必为自己分配任何内存,而且它们有更好的语法。 Check this out for their differences
      • 你说得对!我误解了这个问题。我不知道 C# 7.0 中的本地函数,但现在我想通了。
      • 我想也许你想要一种方法来实现这种行为。
      猜你喜欢
      • 2011-10-15
      • 2019-07-30
      • 2011-03-03
      • 2018-03-08
      • 2020-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多