无法通过继承或泛型去除冗余代码

时间:2010-06-28 21:00:44

标签: c# .net oop

对于模糊的标题感到抱歉,但我不确定如何用一个短语来概括这一点。我有一个带有大量冗余C#代码的情况,它看起来像使用某些继承属性或泛型的某种狡猾技巧可以解决这个问题。但是,我不是一个非常有经验的程序员(尤其是使用C#)而且我看不到解决方案。

这种情况以简化的形式看起来像这样。我有一堆类都继承自一种类型。

public class Foo : SuperFoo
{
     ...
     public Foo SomeMethod() { ... }
}
public class Bar : SuperFoo
{
     ...
     public Bar SomeMethod() { ... }
}
public class Baz : SuperFoo
{
     ...
     public Baz SomeMethod() { ... }
}
...    
public class SuperFoo
{
     ...
}

当需要处理这些对象的集合时会出现问题。我的初稿解决方案(坏的解决方案)看起来像这样:

public void SomeEventHasHappened(...)
{
     ProcessFoos();
     ProcessBars();
     ProcessBazes();
     ...
}

public void ProcessFoos()
{
     ...
     foreach (var foo in fooList)
     {
          ...
          foo.SomeMethod();
     }
}
public void ProcessBars()
{
     ...
     foreach (var bar in barList)
     {
          ...
          bar.SomeMethod();
     }
}

......等等。问题是,除了正在操作的对象的类型之外,ProcessX方法中的所有代码基本上都是相同的。由于显而易见的原因,将所有这些合并到一个方法中会很好。

我的第一个想法是制作一个通用的Process()方法,该方法将List<SuperFoo>作为参数,然后从那里开始。问题是泛型SuperFoo没有SomeMethod(),并且它不能有一个,因为每个子类的SomeMethod()都有不同的返回类型,因此覆盖不起作用。

2 个答案:

答案 0 :(得分:2)

我通常添加一个操作基类型的接口。

interface ISuperFoo
{
    public ISuperFoo SomeMethod() { ... }
}

public class Foo : SuperFoo, ISuperFoo
{
     // concrete implementation
     public Foo SomeMethod() { ... }

     // method for generic use, call by base type
     public ISuperFoo ISuperFoo.SomeMethod() 
     { 
       return SomeMethod(); 
     }
}

public void Processs()
{
     ...
     foreach (var iSuperFoo in list)
     {
          ...
          iSuperFoo.SomeMethod();
     }
}

当然这取决于您使用的结果。

有时你可以使用泛型更容易,但你也可能最终陷入混乱。有时在某个地方倾向于更容易。当然,只要你能负担得起,你就试着避免这种情况。

答案 1 :(得分:2)

以下是一个示例,说明如何使用泛型并使SuperFoo成为抽象类。

public interface ISuperFoo
{
    ...
}

public abstract class SuperFoo<T> where T : ISuperFoo
{
    public abstract T SomeMethod();
}

public class BazReturn : ISuperFoo
{
    ...
}

public class Baz: SuperFoo<BazReturn>
{
    public override BazReturn SomeMethod()
    {
        throw new NotImplementedException();
    }
}

public class BarReturn : ISuperFoo
{
    ...
}

public class Bar : SuperFoo<BarReturn>
{
    public override BarReturn SomeMethod()
    {
        throw new NotImplementedException();
    }
}

public static class EventHandler
{
    public static void SomeEventHasHappened(List<SuperFoo<ISuperFoo>> list)
    {
        foreach (SuperFoo<ISuperFoo> item in list)
        {
            ISuperFoo result = item.SomeMethod();
        }
    }
}

如果需要,你可以用一个具体的类替换ISuperFoo接口,但是你必须抛出那种失败的返回值。

public abstract class SuperFoo<T>
{
    public abstract T SomeMethod();
}

public class Foo : SuperFoo<int>
{
    public override int SomeMethod()
    {
        throw new NotImplementedException();
    }
}

public static class EventHandler
{
    public static void SomeEventHasHappened(List<SuperFoo<int>> list)
    {
        foreach (SuperFoo<int> item in list)
        {
            item.SomeMethod();
        }
    }
}