views:

69

answers:

3

Hi, I'm working on an engine which is meant to be configurable by the user (not end user, the library user) to use different components. For example, let's say the class Drawer must have an ITool, Pencil or Brush, and an IPattern, Plain or Mosaic. Also, let's say a Brush must have an IMaterial of either Copper or Wood

Let's say the effect of choosing Pencil or Brush is really drastically different, and the same goes for the IPattern type. Would it be a bad idea to code the Drawer class with Generic concepts like this :

public class Drawer<Tool, Pattern> where Tool: ITool where Pattern : IPattern { ... }
public class Brush<Material> where Material : IMaterial { ... }

One could then use that class like :

Drawer<Pencil, Mosaic> FirstDrawer = new Drawer<Pencil, Mosaic>();
Drawer<Brush<Copper>, Mosaic> SecondDrawer = new Drawer<Brush<Copper>, Mosaic>();

I mostly used generic for collections and such and haven't really see generics used for that kind of thing. Should I?

+2  A: 

It could work, but it depends whether it is going to be any different to passing an ITool / IPattern in via the constructor. In depends partly on convenience, and partly on whether you do anything interesting with the template parameters (for example, new them).

To be honest, the example given does not leap to mind as a good fit for generics - you can't conveniently have a set of brushes, for example (unless you have some additional abstraction - perhaps IBrush - not shown).

The standard winforms (system.drawing.dll) does this via static properties, like Pens.Red, Brushes.Blue (for a basic solid brush) - maybe take some inspiration from there? or maybe not. Up to you.

Marc Gravell
In fact, it's not a "Drawer" at all I'm making, it's a simple 2D Collision engine :-)
Tipx
+2  A: 

In this situation I would favour composition over generics. I imagine whilst the tool will be the responsibility of the drawer, the pattern will be the responsibility of the tool.

public class Drawer
{
    private ITool _tool;

    public Drawer(ITool tool, IPattern pattern)
    {
        _tool = new Tool(pattern);
    }
    ...
}

public class Tool : ITool
{
    private IPattern _pattern;

    public Tool(IPattern pattern)
    {
        _pattern = pattern;
    }
    ...
}
Evil Andy
+1  A: 

It does not really make sense using generics unless the engine you are creating have methods with arguments or return types of the generic type. I.e. you would expect there to be a propertie and methods like

public <Material> Material { get; }
public void Draw(<Tool> pen);

(I am currently in a Java mode so please correct the C# syntax if wrong!)

From what I can tell from the example you are only using generics for the constructor of the classes. Since you are relying on the interfaces in your implementation the use of generics does not really add value.

Perhaps I am mistaken but generics is really for type safety checked at compile time and to avoid a lot of (risky) type casting.

Christoffer Soop
Thanks, the part about "unless the engine you are creating have methods with arguments or return types of the generic type" really helped me realize how pointless it would have been to use Generics in that case!Sure it would work using generics, but it would be using generics just for using generics :-P
Tipx