Mirrana
Mirrana

Reputation: 1731

C# equivalent of Java Class<? extends Base>?

I'd like to be able to write a method in C# similar to how I would in Java... To pass in a Class object that is a subclass of some super class... but the best I can find for C# is the following:

public void someMethod(Type t) {
  if (t == typeof(SomeType)) ...
}

Is there any way I can enforce in the method signature that the parameter has to be either the type SomeType or one of its inheritors?

I'm not looking to pass in an instance of said Type. I want to pass the Type itself in as a parameter.

Edit

Here's a bit of context.

I want to make an EventManager class that contains a Dictionary<SomeEventType, ICollection<EventHandler>> object, and a method registerEventHandler(Type t, EventHandler eh) that maps a given Type to an EventHandler.

In Java, I would accomplish it as such:

private static Map<Class<? extends Event>, Collection<EventHandler>> eventHandlers;

public static void registerListener(Class<? extends Event> event, EventHandler handler) {
  if (eventHandlers.get(event) == null) {
    HashMap<EventHandler> handlers = new HashMap<EventHandler>()
    eventHandlers.put(event, handlers) ...
  }
}

Upvotes: 6

Views: 3188

Answers (4)

recursive
recursive

Reputation: 86134

You could use a generic constraint.

public void someMethod<T>() where T : SomeType {
    Type myType = typeof(T);

    // do something with myType
}

Here's an implementation of your desired use case.

class EventManager {
    public Dictionary<Type, ICollection<EventHandler>> 
        HandlerMap = new Dictionary<Type, ICollection<EventHandler>>();

    public void RegisterEventHandler<TEvent>(EventHandler eh) 
        where TEvent: SomeEventType 
    {
        Type eventType = typeof(TEvent);

        if (!HandlerMap.ContainsKey(eventType)) {
            HandlerMap[eventType] = new List<EventHandler>();
        }

        HandlerMap[eventType].Add(eh);
    }
}

You would call it like this.

var em = new EventManager();
EventHandler eh = null; // or whatever
em.RegisterEventHandler<SpecificEventType>(eh);

Upvotes: 10

Jon Skeet
Jon Skeet

Reputation: 1502556

As others have said, you can do this with a generic type parameter... but if you only have the value as a Type and want to pass it in as a regular argument (e.g. because it's been passed to your method that way), there's no way of doing it. Type isn't generic in .NET, so there's no concept of constraining the parameter to be the Type representing a particular class or its subclasses, just as there's no concept of constraining a string parameter to be of a certain length or longer.

If you do know the types at compile-time when calling the method, then using a generic type parameter as per recursive's answer is absolutely the way to go.

Upvotes: 1

Fredou
Fredou

Reputation: 20120

i don't really know java but you mean something like this?

namespace ConsoleApplication1
{
    class bar
    { public void stuff() { } }

    class foo : bar
    { }

    class doublefoo : bar
    { }

    class Program
    {
        static void Main(string[] args)
        {
            someMethod<foo>();
            someMethod<doublefoo>();
        }

        public static void someMethod<t>() where t: bar, new()
        {
            t myBar = new t();

            myBar.stuff();
        }
    }
}

Upvotes: 1

Jason W
Jason W

Reputation: 13199

You can have the behavior through defining a generic type.

public void SomeMethod<T>(T obj) where T : AbstractClass
{
}

But nothing also prevents you from just using the base class as the parameter

public void SomeMethod(AbstractClass obj)
{
}

Upvotes: 1

Related Questions