使用多种方法签名时的DRY原则

时间:2015-02-11 12:17:05

标签: c# generics dry method-signature

考虑到DRY原则,您将如何处理与IEnumerable一起使用的几乎相同的方法(具有不同的签名)。即一个签名适用于特定类型参数。我的问题扩展到调用私有方法及其多重签名。

我不想让两个方法具有相同的逻辑 - 如果有什么变化,那么我必须改变两组逻辑。例如,调用私有方法,如何使私有方法接受任何类型的IEnumerable

public class Person
{
    public string Name {get; set;}
    public string Age {get; set;}
}

public class SupremeBeing : Person
{
    public string Power {get; set;}
}

public class Payroll
{
    public void DoSomething(IEnumerable<Person> peopleIn)
    {
        // Do this with peopleIn
        // Do that with peopleIn
        // Call private method passing in peopleIn (which also has 2 signatures)
    }

    public void DoSomething(IEnumerable<SupremeBeing> peopleIn)
    {
        // Do this with peopleIn
        // Do that with peopleIn
        // Call private method passing in peopleIn (which also has 2 signatures)
    }       
}

5 个答案:

答案 0 :(得分:3)

在我看来,你想要的是Payroll Class

上更多的抽象
public abstract class PayrollBase<T> where T : Person
{
    public void DoSomething(IEnumerable<T> peopleIn)
    {
        // Do this with peopleIn
        // Do that with peopleIn
        this.InternalLogic(peopleIn);
    }

    protected virtual InternalLogic(IEnumerable<T> peopleIn)
    {
       // do something super special
    }
}

然后,您可以针对特定类型实施此操作

public PersonPayroll : PayrollBase<Person>
{
    protected override InternalLogic(IEnumerable<Person> peopleIn)
    { ... } 
}


public SupremeBeingPayroll : PayrollBase<SupremeBeing>
{
    protected override InternalLogic(IEnumerable<SupremeBeing> peopleIn)
    { ... } 
}

然后,您将使用某种形式的工厂类来为您正在处理的人员列表实例化正确的“工资单”。

答案 1 :(得分:2)

面向对象的方法是让类自己处理它们的差异。例如,您可以使用虚方法为每个类创建一个实现。

当您可以将每个对象视为Person对象而不管实际类型时,您只需要一组方法来处理工资单,而您不需要为每个对象分别调用它class,你可以将它们全部放在同一个列表中并调用方法。

示例:

public class Person {

  public string Name {get; set;}
  public string Age {get; set;}

  virtual public int Salary { get { return 1000 + Age * 10; } }

  override public string ToString() {
    return Name + "(" + Age + ")";
  }

}

public class SupremeBeing : Person {

  public string Power {get; set;}

  override public int Salary { get { return 5000 + Age * 7; } }

  override public string ToString() {
    return Power + " " + Name;
  }

}

public class Payroll {

  public void DoSomething(IEnumerable<Person> peopleIn) {
    foreach (Person p in peopleIn) {
      Console.log("{0} earns {1}", p, p.Salary);
    }
  }

}

答案 2 :(得分:1)

一种选择是从第二种方法调用第一种方法:

public void DoSomething(IEnumerable<SupremeBeing> peopleIn)
{
    this.DoSomething(peopleIn.Cast<Person>());

    // do SupremeBeing specific stuff
}

另一个选择是使用一个私有方法来执行所有Person个东西。

public void DoSomething(IEnumerable<SupremeBeing> peopleIn)
{
    this.DoSomethingWithPersons(peopleIn);
}

public void DoSomething(IEnumerable<Person> peopleIn)
{
    this.DoSomethingWithPersons(peopleIn);
}

private void DoSomethingWithPersons(IEnumerable<Person> peopleIn)
{
    // do stuff
}

两个选项之间的细微差别没有更多信息,很难知道哪个更好。

答案 3 :(得分:0)

我不明白你的问题。您可以创建一个通用方法来执行您的泛型,然后创建一个可以为您的特殊内容覆盖的方法。

像:

class Something
{
    protected virtual void DoSomethingSpecial<TYPE>(TYPE item)
    {
    }

    public void DoSomethingy<TYPE>(IEnumerable<TYPE> items)
    {
        foreach(TYPE item in items)
        {
          // do whatever you have to do for every type

          // do whatever you have to do in special
          this.DoSomethingSpecial(item)
        }
    }
}

仅对输入的代码进行了测试。

然后为每个特例创建一个类。在这些类中,您只需覆盖每种类型的DoSomethingSpecial即可。

答案 4 :(得分:0)

您可以让Payroll类在运行所有常见操作并将人员转发到适当的扩展方法后,对不同类型的人员进行排序。

interface IPerson {
    string Name { get; set; }
    string Age { get; set; }

}
public class Person : IPerson {
    public string Name { get; set; }
    public string Age { get; set; }
}
public class SupremeBeing : Person
{
    public string Power { get; set; }
}

public class Payroll 
{
    public void DoSomething(IEnumerable<IPerson> peopleIn)
    {
        //..everyone does this and that 
        IEnumerable<Person> NormalPeople = peopleIn.OfType<Person>();
        if (NormalPeople.Count() > 0) DoSomethingNormalSpecific(NormalPeople);

        IEnumerable<SupremeBeing> SupremeBeings = peopleIn.OfType<SupremeBeing>();
        if (SupremeBeings.Count() > 0) DoSomethingSupremeSpecific(SupremeBeings);

    }

    public void DoSomethingNormalSpecific(IEnumerable<Person> normalPeopleIn) 
    {
        // just normal people
    }

    public void DoSomethingSupremeSpecific(IEnumerable<SupremeBeing> supremeBeingsIn)
    {
        // just Supreme Beings
    }
}