Checking type parameter of a generic method in C#
Solution 1:
Yes:
if (typeof(T) == typeof(MyClass))
{
MyClass mc = (MyClass)(object) t;
}
else if (typeof(T) == typeof(List<MyClass>))
{
List<MyClass> lmc = (List<MyClass>)(object) t;
}
It's slightly odd that you need to go via a cast to object, but that's just the way that generics work - there aren't as many conversions from a generic type as you might expect.
Of course another alternative is to use the normal execution time check:
MyClass mc = t as MyClass;
if (mc != null)
{
// ...
}
else
{
List<MyClass> lmc = t as List<MyClass>;
if (lmc != null)
{
// ...
}
}
That will behave differently to the first code block if t
is null, of course.
I would try to avoid this kind of code where possible, however - it can be necessary sometimes, but the idea of generic methods is to be able to write generic code which works the same way for any type.
Solution 2:
Starting with C# 7, you can do this in a concise way with the is
operator:
public void DoSomething<T>(T value)
{
if (value is MyClass mc)
{
...
}
else if (value is List<MyClass> lmc)
{
...
}
}
See documentation: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/is#pattern-matching-with-is
Solution 3:
It's 2017 and we have now C# 7 with pattern matching. If your type T inherit object
you can you code like this
void Main()
{
DoSomething(new MyClass { a = 5 });
DoSomething(new List<MyClass> { new MyClass { a = 5 }, new MyClass { a = 5 }});
}
public void DoSomething(object t)
{
switch (t)
{
case MyClass c:
Console.WriteLine($"class.a = {c.a}");
break;
case List<MyClass> l:
Console.WriteLine($"list.count = {l.Count}");
break;
}
}
class MyClass
{
public int a { get; set;}
}
Solution 4:
I believe there's something wrong in your design. You want to compare between types in an already generic method. Generics are meant to deal with type-variable situation. I recommend to do it this way..
//Generic Overload 1
public void DoSomething<T>(T t)
where T : MyClass
{
...
}
//Generic Overload 2
public void DoSomething<T>(T t)
where T : List<MyClass>
{
...
}