Checking type parameter of a generic method in C#

前端 未结 4 1099
再見小時候
再見小時候 2020-12-02 19:56

Is it possible to do something like this in C#:

public void DoSomething(T t)  
{
    if (T is MyClass)
    {
        MyClass mc = (MyClass)t 
               


        
相关标签:
4条回答
  • 2020-12-02 20:09

    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.

    0 讨论(0)
  • 2020-12-02 20:22

    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>
    {
        ...
    }
    
    0 讨论(0)
  • 2020-12-02 20:26

    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

    0 讨论(0)
  • 2020-12-02 20:28

    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;}
    }
    
    0 讨论(0)
提交回复
热议问题