Related to C# - Is there a better alternative than this to 'switch on type'?
I need to 'switch on types': given a parameter of type T
, find and execute a method of the form void Method (T param)
.
This could be solved with a switch statement or a Dictionary<Type, Action>
, however I would like to avoid the casts necessary in such scenarios.
I couldn't find the following approach mentioned in the above (or similar) questions:
Create a static generic type that acts as collection:
public static class Commands<T> { public static Action<T> Handler; }
Create a repository which uses that type like a type-safe dictionary:
public class CommandRepository { public void Register<T>(Action<T> handler) { Commands<T>.Handler = handler; } public void Run<T>(T parameter) { // null checks etc. Commands<T>.Handler(parameter); } }
Example usage:
public void CreateUser(CreateUserParams p) { Console.WriteLine("Creating " + p.Name); } // ... var repo = new CommandRepository(); repo.Register<CreateUserParams>(CreateUser); repo.Register<DeleteUserParams>(DeleteUser); repo.Run(new CreateUserParams { Name = "test" }); repo.Run(new DeleteUserParams { Name = "test" });
As mentioned before, the same behavior could be achieved with a Dictionary<Type, Action>
in the ComandRepository
, but then I would have to cast either the method parameter or, if I use interfaces instead of Action
, cast to an IFoo<T>
after acquiring an dictionary item.
My question is: Is it OK to (ab-)use generic types like that (given a large number of possible values for T
)?
(Bonus question) If it isn't OK, why exactly not? What are the costs / negative effects this would cause?
A final note: I realize this doesn't work for type hierarchies or interfaces. Type T
must be matched exactly, which in my scenario is fine.
Edit: I found out that Jil, a JSON serializer, also relies on this pattern. See the TypeCache
type, which stores a delegate to serialize an object of type T
(as far as I've understood from skimming through code). Since this TypeCache
will store a large amount of types I suppose the pattern is generally not problematic.
It would still be interesting to know whether types or their static members need to be garbage collected or if there are other performance implications that need to be considered.