Sign in to follow this  
Nanoha

c# generics

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Nanoha
I 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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this