为什么Action/Func比.Net中的常规方法更好?

Jam*_*ght 12 .net c# action func

如果我需要快速可重复使用的代码,我更喜欢使用Action或Func,但是我团队中的其他人不喜欢它们或理解它们.
目前,我唯一真正的论点是关于偏好和更新的代码实践,但这些只是不好的论点.

为什么这样做更好:

Action<FormView,String> hideControl = (form,name) => {
    var button = form.GetControl<Button>(name);
    if (button != null)
        button.Visible = false;
}
Run Code Online (Sandbox Code Playgroud)

比:

public static void HideControl<T>(this FormView form, string name) where T : Control
{
    var button = form.GetControl<Button>(name);
    if (button != null)
        button.Visible = false;
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以给我具体的具体论据/例子吗?

dth*_*rpe 33

你的问题有两个方面:风格和表现.

对于代码样式,使用委托使事情变得有点混乱.没有与代码体(匿名方法)相关联的函数名,推断了参数类型,并且当过度使用时,这可能导致在委托中包含许多较小的独立代码块的大型功能块.看起来并不漂亮,很难弄清楚代码实际上在做什么,而且很难找到你想要的东西.

为了提高性能,委托引入了一个间接性,它不像普通的旧方法那样快.差异很小,但是当过度使用时,它会变得明显.

任何工具都有适当和过多的用途.当您想要将回调例程传递给函数时,使用Action或Func作为回调参数是合适的.使用Action或Func作为声明函数的替代是一种误用,即IMO.

  • +1"替换声明功能一般是滥用". (6认同)
  • Action/Func作为代理实现.委托在IL中实现为编译器生成的类,具有Invoke()方法.当foo是委托时调用foo()实际上编译为调用foo.Invoke(),后者又调用目标代码.如果foo是一个实际的方法而不是委托,则调用foo()直接调用没有Invoke()中间的目标代码.请参阅ILDASM以获取证明. (3认同)
  • @Kiquenet ECMA 335,第二部分14.6.http://www.ecma-international.org/publications/standards/Ecma-335.htm (3认同)

Joh*_*nan 18

简短的回答是,总的来说,并不是更好.我同意你的队友.

我不认为你的问题是正确的.而不是问为什么它更好(相信我不是在大多数情况下),你可能会问它什么时候更好.

现在,有些时候它们非常有用,比如在LINQ中,当方法接受Func时,写一个快速的lambda很棒.

这更具可读性和可维护性:

var myQuery = Customers.Where(x => x.ID == 3).First();
Run Code Online (Sandbox Code Playgroud)

比另类:

public bool FilterByID3(Customer cust)
{
  return cust.ID == 3;
}

    var myQuery = Customers.Where(FilterByID3).First();
Run Code Online (Sandbox Code Playgroud)

在大多数其他情况下,使用函数更具可读性/可维护性.

  • 来自我的+1.我发现函数更具可读性.另外,文档生成器如何处理操作?他们呢? (4认同)

Tho*_*que 9

为什么这样做更好

这不是更好.在这种情况下,我认为这样做没有任何优势,而不是写一个真正的方法.如果你不能,我不明白你为什么这么肯定它会更好.

避免编写长匿名方法(并且长,我的意思是超过一两行),它只会使代码不易读取.

但是在某些情况下,使用匿名方法可能很有用:闭包.如果您需要捕获局部变量,那么匿名方法就是您的选择.但即便如此,也不要在其中编写很长的代码:只需调用一个将捕获的变量作为参数传递给它的实际方法.


Chr*_*Wue 8

总的来说,我同意其他的回答:盲目地用Action/ 取代函数定义Func并不是一件好事.ActionFunc不是 .NET的未来.它们是一个非常有用工具,但任何工具都可能被滥用.

所以,如果你倾向于编写这样的代码

class SomeClass {
    Action<...> a1 = (..) => {};
    Func<...> f1 = (..) => {};
    Action<...> a2 = (..) => {};
    ...
}
Run Code Online (Sandbox Code Playgroud)

这当然不是一件好事.

如果你这么做了:

  void SomeMethod()
  {
      Action<..> a = (..) => {};
      ...
      a();
  }
Run Code Online (Sandbox Code Playgroud)

那么这实际上是一种封装小辅助方法而不会污染类的好方法.

为了证明你的具体情况:如果hideControl仅在非常具体的情况下使用私有帮助方法将是首选.如果需要很多,FormViews那么扩展方法更有意义.扩展方法也是一种可以被滥用的工具,因为它可能导致类的公共接口的污染.虽然您可以通过使用命名空间来限制它.

我通常遵循这个准则:如果你需要一个在很多地方和情况下都很有用的辅助方法,并且可以做得相当通用我创建一个扩展方法.如果它是特定类所需的辅助方法,但在该类的几个地方(方法)中,那么我创建一个私有方法.如果它是一个帮助器,我只需要在一个特定的地方,那么我在该方法中使它成为一个Action/Func.


Aus*_*nen 7

优点

  • 关闭
    • 但这对你的情况没有帮助.
  • 超私有方法 - 只有定义方法才能调用它.
    • 尽管如此,这很容易与单一责任原则相抵触.您可能在整个方法中组合应该是不同的类.
  • 回调
    • 这些也很容易成为方法.

缺点

  • 在我看来,由于压痕过多(我不是粉丝),可读性会降低.
  • 调试变得有点困难,因为您的调用堆栈不太直观,特别是当您定义了多个Func/时Action.

你必须在你的环境中克服缺点.

我很好奇你的"更新的编码实践"论点.仅仅因为你可以尽可能地做到这一点并不意味着你应该这样做.