c# generics

This topic is 2981 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

hello, I am trying to do some input handling by regestering "InputHandlers" with my input handleing class. For simplicity Sake sake I have "Player" object, it would then have an object "PlayerInputHandler" that it owns and that contains a reference to the Player. It registers this with the input handler, when the input handler has a key pressed it calls "KeyDown" on the PlayerInputHandler. The handler can do whatever I want BUT what I notice is that all I do is call OnKeyDown on my player and forward it on. I do this on several classes so the input handler just becomes an input forwarder. I realise I could make my objects a type of input handler but I dont' want to. So what I am trying to do is make a generic "InputForwarder" class like so:
    class InputForwarder<T> :  InputHandler
{
T forwardObject;

public InputForwarder(T target)
{
forwardObject = target;
}

public override void OnKeyDown(Keys key)
{
forwardObject.KeyDown(key);
}

public override void OnKeyUp(Keys key)
{
forwardObject.KeyUp(key);
}
}

However it won't compile and I can't figure out why. Errors are on the following: forwardObject.KeyDown(key); forwardObject.KeyUp(key); The error is: error CS1061: 'T' does not contain a definition for 'KeyUp' and no extension method 'KeyUp' accepting a first argument of type 'T' could be found checking that error it just means my class doens't have the method but I thought this would only be an issue when I actually try to make an object of this type (not got that far). I've read a bit about generics trying to solve this problem but I don't see any examples doing this. Any help is most appreciated. Thanks.

Share on other sites
There are a couple ways I usually solve that kind of design:

1. Put a constraint on the generic type:
class InputForwarder<T> : InputHandler where T: IForwardObject

or since you probably would constrain on an interface anyway, just simplify it as...

2. Replace the <T> with an interface:
public interface IForwardObject{  void KeyDown(Keys key);  void KeyUp(Keys key);}class InputForwarder : InputHandler{  IForwardObject forwardObject;}

Personally I always go with #2.

Share on other sites
I saw those constrains things, didn't really understand them. I like the sound of 2) but I don't have to make my Player etc objects inherit from IForwardObject do I?

I'll give it a shot tommorow.

Share on other sites
Yes, you must inherit from C# interfaces to make them work. And you need to have a 'minimal' interface constraint to a generic in order to actually do stuff with the generic beyond object stuff.

Share on other sites
Quote:
 Original post by NanohaI like the sound of 2) but I don't have to make my Player etc objects inherit from IForwardObject do I?

You could (you can multiple-inherit from interfaces cleanly in C#).

If you want to decouple things some more you could make a separate class like this (not sure what the name of this pattern is, but I'm guessing it's the degenerate form of Chain of Responsibility):

class PlayerInputForwarder : IInputForwarder{  Player player;  ctor(Player player) { this.player = player; }    // Implement the interface's KeyDown/KeyUp in this class.  // Depending on accesibility you might want to make this a nested class inside the player class.}

I usually only make these kinds of classes during refactoring when one class (such as Player) gets too messy.