Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having trouble getting rid of redundant code via inheritance or generics

Tags:

c#

.net

oop

Sorry for the vague title, but I wasn't sure how to summarize this in one phrase. I have a situation with a lot of redundant C# code, and it really looks like some kind of crafty trick using some property of inheritance or generics would solve this. However, I'm not a terribly experienced programmer (particularly with C#) and just can't quite see the solution.

The situation, in simplified form, looks something like this. I have a bunch of classes that all inherit from one type.

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

The problem comes when collections of these objects need to be processed. My first-draft solution (the bad one) looks like this:

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();
     }
}

...and so on. The problem is that basically all of the code in the ProcessX methods is the same, other than the type of the objects that are being operated on. It would be nice to consolidate all of these into one method for obvious reasons.

My first thought was to just make a generic Process() method that took a List<SuperFoo> as a parameter and just proceed from there. The problem is that a generic SuperFoo does not have a SomeMethod(), and it can't have one because each of the child classes' SomeMethod() has a different return type, so having overrides doesn't work.

like image 820
jloubert Avatar asked Oct 15 '22 03:10

jloubert


1 Answers

I usually add an interface which operates on base types.

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();
     }
}

Of course it depends what you are using the result for.

Sometimes you can make it easier using generics, but you also can end up in a mess. Sometimes it is just easier to downcast somewhere. Of course, you try to avoid this whenever you can afford it.

like image 150
Stefan Steinegger Avatar answered Oct 18 '22 14:10

Stefan Steinegger