3

There are lots of answers on how to switch on type in older versions of C#. My question has to do with how to switch on the type called out in a generic method:

 public T GetAxis<T>(object axisObject) { switch (typeof(T)) { case Axis: //...do something break; } return null; } 

I am getting an error on the line:

case Axis axis: 

The error is:

The expression of type 'System.Type' cannot be handled by a pattern of type 'MyNamespace.Axis'.

I believe my question is how do I get the Type being called out in the <> specification so I can switch on it.

3
  • 5
    Well, to be honest: if you're switching on the T it isn't truly generic - but: if (typeof(T) == typeof(Axis)) {...} maybe? Or create a dictionary that maps Type to some enum of the expected types, and switch on that? Commented Nov 9, 2021 at 21:54
  • Are you truly trying to switch on the generic T, or are you trying to switch on the type of axisObject? Commented Nov 9, 2021 at 21:57
  • Why would you want to do this? Really do something should be defined by that type, so you can just constrain T to implement a method void DoSomething() Commented Nov 9, 2021 at 22:06

2 Answers 2

3

Newer versions of C# haven't added any features specifically around switching on Type values. If you're truly attempting to switch based on a generic type, you'll probably want to follow the patterns recommended in those other SO posts.

However, there may be better approaches than using generic types. The fact that you're trying to switch on that type implies that there are limited types you'd expect code to use when calling your method. In that case, you may be better off explicitly using different methods for each of those types.

Instead of:

var axis = GetAxis<Axis>(axisObject); var somethingElse = GetAxis<SomethingElse>(axisObject); 

Use:

var axis = GetAxis(axisObject); var somethingElse = GetSomethingElse(axisObject); 

Your example doesn't appear to be doing this, but if what you're really trying to switch off of is the type of the passed-in object, then newer versions of C# do provide some better options through pattern matching. For example:

public T GetAxis<T>(object axisObject) { switch (axisObject) { case Axis axis: //...do something with `axis` break; case SomethingElse somethingElse: //...do something with `somethingElse` break; } return default; } 

In this last case, it's unclear to me what value the T generic type has: you may be able to replace that with a non-generic return type.

Sign up to request clarification or add additional context in comments.

Comments

0

When dealing with this kind of thing I tend to resort to the following dictionary:

private Dictionary<Type, Delegate> _axisCases = new Dictionary<Type, Delegate>(); 

You can write this kind of code around it:

public class MyCode { public MyCode() { this.SetCase<Axis>(o => new Axis()); } private Dictionary<Type, Delegate> _axisCases = new Dictionary<Type, Delegate>(); private void SetCase<T>(Func<object, T> func) { _axisCases[typeof(T)] = func; } public T GetAxis<T>(object axisObject) where T : class { var t = typeof(T); if (_axisCases.ContainsKey(t)) { var func = (Func<object, T>)_axisCases[t]; return func(axisObject); } return null; } } 

Now you can call it like this:

var myCode = new MyCode(); var axis = myCode.GetAxis<Axis>(new object()); 

This type of code is the most flexible. But if you want something closer to a normal case statement

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.