Reputation: 1731
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.
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
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
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
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
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