【问题标题】:How to avoid code duplication here?如何避免这里的代码重复?
【发布时间】:2012-05-23 10:14:19
【问题描述】:

我在一个类中有两种方法,一种带有额外参数

第一个:

public override void CalcV(IV iv)
{
     initializations
     otherOperations

     for (int i=0; i < NUM; ++i)
     {
         SomeOtherOperations
         double v = GetV(a,b,c);
         SomeOtherOperationsUsing_v
     }

     restOfOperations
}

第二个:

public override void CalcV(IV iv, int index)
{
     initializations
     otherOperations

     for (int i=0; i < NUM; ++i)
     {
         SomeOtherOperations
         double v = GetV(a,b,c, index);
         SomeOtherOperationsUsing_v
     }

     restOfOperations
}

你可以看到唯一的区别是第一个调用 GetV() 带有 3 个参数,第二个调用 GetV() 的重载带有 4 个参数。

如何才能最好地避免代码重复?

谢谢!

【问题讨论】:

  • 当然,有一个默认索引,你可以使用

标签: c# oop code-duplication overloading duplication


【解决方案1】:

假设您不知道合理的默认值,一个非常简单的方法是:

public override void CalcV(IV iv)
{
    CalcV(iv, null);
}

public override void CalcV(IV iv, int? index)
{
     ...
     double v = index.HasValue ? GetV(a,b,c,index.Value) : GetV(a,b,c);
     ...
}

【讨论】:

  • 其他一些答案假设 1) GetV(a,b,c,0) == GetV(a,b,c) 或/和 2) index 是严格非-消极的。现在和将来都不一定如此。我的方法假设两者都没有。
【解决方案2】:

如果您使用的是 .Net 4.0,则可以将其设为可选参数:

public override void CalcV(IV iv, int index = -1)
{
    ....
    double v = index > -1 ? GetV(a,b,c, index) : GetV(a,b,c);

    ....
}

【讨论】:

  • 非常接近,但如果没有更多上下文,您无法确定 GetV 不接受 index 的负值。
  • 谢谢戴夫!显然我需要一些咖啡!
  • 你能有一个负索引吗?我从来没有从哲学上考虑过:D ....
  • @DaveBish:负索引的概念是从末尾倒数。 IE。 -1 的索引是最后一个元素。
【解决方案3】:

猜测 GetV 的功能(您需要更改它以适应:

public override void CalcV(IV iv)
{
     CalcV(iv, 0);
}


public override void CalcV(IV iv, int index)
{
     initializations
     otherOperations

     for (int i=0; i < NUM; ++i)
     {
         SomeOtherOperations
         double v = GetV(a,b,c, index);
         SomeOtherOperationsUsing_v
     }

     restOfOperations
}

【讨论】:

  • 是的,无论是那个参数还是默认参数——不管你的船是什么:)
  • 嗯...这可能不会这样做,因为正如您所说,您猜测带有三个参数的 GetV 与带有四个参数的 GetV 相同。
  • @Sani Huttunen - 我同意 - 这就是答案开头的评论的目的 - 原始问题中没有足够的细节,但给出了如何去做的一般要点......
【解决方案4】:
public override void CalcV(IV iv, int? index = null)
{
     initializations
     otherOperations

     for (int i=0; i < NUM; ++i)
     {
         SomeOtherOperations
         double v = index != null ? GetV(a,b,c, index) : GetV(a,b,c);
         SomeOtherOperationsUsing_v
     }

     restOfOperations
}

然后您可以删除第一个覆盖,这将处理这两种情况。

【讨论】:

  • 这真的很好 - 最好的答案,因为它既简短又正确,没有任何假设。
  • 谢谢你,它的灵感来自于你对 null 的使用!
【解决方案5】:

我假设 index 是基于 0 的正数:

public override void CalcV(IV iv, int index)
{
  initializations
  otherOperations

  for (int i=0; i < NUM; ++i)
  {
    SomeOtherOperations
    double v = index == -1 ? GetV(a, b, c) : GetV(a,b,c, index);
    SomeOtherOperationsUsing_v
  }

  restOfOperations
}

然后你调用索引为 -1 的函数,如果你想用四个参数调用 GetV,你想使用 GetV 和一个“正确”索引。

public override void CalcV(IV iv)
{
  return CalcV(iv, -1);
}

【讨论】: