【问题标题】:Is there a more efficient approach than C# Action delegates for avoiding this code duplication?有没有比 C# Action 委托更有效的方法来避免这种代码重复?
【发布时间】:2012-03-22 15:57:04
【问题描述】:

我想尽可能避免不必要的代码重复。在下面描述的场景中,我使用了Action 委托来避免代码重复。但是,当使用Action 委托方法时,代码会变慢大约 50%-80%。

从性能的角度来看,有没有比Action 委托更有效的方法来避免下面描述的场景中的代码重复?

除了长循环的最里面的语句之外,我有两种等效的方法:

public T[] MethodA<T>(T[] from)
{
  ...
  for (var i = 0; i < len; ++i)
  {
    var j = GetIndex(i);
    to[j] = from[i];    // This statement differs in MethodA and MethodB
  }
  ...
  return to;
}

public T[] MethodB<T>(T[] from)
{
  ...
  for (var i = 0; i < len; ++i)
  {
    var j = GetIndex(i);
    to[i] = from[j];    // This statement differs in MethodA and MethodB
  }
  ...
  return to;
}

为了避免代码重复,我实现了一个辅助方法,该方法采用Action 委托。调用委托会替换变量语句,如下所示:

private T[] HelperMethod<T>(T[], Action<T[], T[], int, int> action)
{
  ...
  for (var i = 0; i < len; ++i)
  {
    var j = GetIndex(i);
    action(from, to, i, j);    // Invoke the Action delegate
  }
  ...
  return to;
}

那么我可以将MethodAMethodB减少如下:

public T[] MethodA<T>(T[] from)
{
  return HelperMethod(from, (src, dest, src_idx, dest_idx) => dest[dest_idx] = src[src_idx]);
}

public T[] MethodB<T>(T[] from)
{
  return HelperMethod(from, (src, dest, dest_idx, src_idx) => dest[dest_idx] = src[src_idx]);
}

请注意,重构后的MethodAMethodB 之间的唯一区别是HelperMethod 调用的Action 签名中src_idxdest_idx 的顺序。

【问题讨论】:

  • 您是如何衡量 50-80% 的性能下降的?听起来不太可能
  • 我在重构前后的单元测试中进行了时序比较。当然,上面的代码是我实现的简化版本,但在重构之前经过的时间(使用单元测试中的 Stopwatch 类测量)是 1.6-1.8 秒,而在重构之后经过的时间是 2.6-2.7 秒。跨度>
  • 它不太可能通过任何形式的函数调用来击败直接分配 - 因此,如果它对性能至关重要,那么您已经有了适合您的解决方案......
  • 是的,你说得对,阿列克谢,谢谢。在受 democodemonkey 下面的响应启发的进一步测试之后,幸运的是,在循环内测试布尔值非常便宜,所以我的解决方案是坚持直接分配,在循环的每次迭代中都会测试分配路线。跨度>
  • 循环是否与编写的完全一致,或者您错过了更多代码?您可以将 if 移动到循环之外,然后复制循环的内容......有点中间立场。

标签: c# delegates refactoring code-duplication


【解决方案1】:

您可以将参数传递给方法并根据参数执行 A 或 B。
我不喜欢它,但我只是说可以做到。我其实更喜欢 Action 方式。

【讨论】:

  • 谢谢。没错,我曾考虑过这一点并将其驳回,因为那时我需要为循环中的每个项目执行ifswitch 或类似的语句。从上面的示例中并不能完全看出这一点,但循环中还包含很多我不想复制的代码。
  • 再想一想,我最初在没有测试的情况下就放弃了这种方法:-) 显然,if 语句非常“便宜”,因为使用时重构前后的时间大致相同(bool) 参数方法。我会去这个解决方案。谢谢,@demoncodemonkey!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 2016-02-22
  • 1970-01-01
  • 2013-01-17
相关资源
最近更新 更多