C# Generic Method, cannot implicit convert

前端 未结 4 1358
旧时难觅i
旧时难觅i 2021-01-11 20:32

I\'ve got the following code:

public static T GetCar() where T : ICar
{
    T objCar = default(T);

    if (typeof(T) == typeof(SmallCar)) {
                


        
相关标签:
4条回答
  • 2021-01-11 21:04

    Your code is illegal because while you might be testing and know that your given T is BigCar or some other such type, the compiler cannot know that in advance and therefore the code is illegal. Based upon your given usage, you could have

    public static T GetCar<T>() where T : ICar, new()
    {
        return new T();
    }
    

    The new() constraint allows you to invoke the default (parameterless) constructor on a type.

    0 讨论(0)
  • 2021-01-11 21:07

    You can simplify your code

    public static T GetCar<T>()
        where T : ICar, new()
    {
        return new T();
    }
    
    0 讨论(0)
  • 2021-01-11 21:07

    Generics is a run-time concept. Information of the types used in a generic data type regardless if its a value or reference type can be obtained at run-time using reflection.

    When a code with T is compiled into MSIL it only identifies it as having a type parameter. Therefore generic type parameter T is not known at compile-time.

    class Program
    {
        static void Main(string[] args)
        {
            ICar smallCar = Helper.GetCar<SmallCar>("car 1");
            ICar mediumCar = Helper.GetCar<MediumCar>("car 2");
    
            Console.ReadLine();
        }
    }
    
    static class Helper
    {
        public static T GetCar<T>(string carName) where T : ICar
        {
            ICar objCar = default(T);
    
            if (typeof(T) == typeof(SmallCar))
            {
                objCar = new SmallCar { CarName = carName };
            }
            else if (typeof(T) == typeof(MediumCar))
            {
                objCar = new MediumCar { CarName = carName };
            }
    
            return (T)objCar;
        }
    
    }
    
    interface ICar
    {
        string CarName { get; set; }
    }
    
    class SmallCar : ICar
    {
        public string CarName { get; set ; }
    }
    
    class MediumCar : ICar
    {
        public string CarName { get; set; }
    }
    
    0 讨论(0)
  • 2021-01-11 21:09

    You cannot convert to T because of the fact that T isn't known at compile time. If you want to get your code to work you can change the return type to ICar and remove the generic T return type.

    You also can cast to T. This would work too. If you only using the default constructor you can also constain on new() and use new T() to get your code to work.

    Samples

    public ICar GetCar<T>()
        where T : ICar
    {
        ICar objCar = null;
    
        if (typeof(T) == typeof(SmallCar)) {
            objCar = new SmallCar();
        } else if (typeof(T) == typeof(MediumCar)) {
            objCar = new MediumCar();
        } else if (typeof(T) == typeof(BigCar)) {
            objCar = new BigCar();
        }
    
        return objCar;
    }
    

    Cast:

    public T GetCar<T>()
        where T : ICar
    {
        Object objCar = null;
    
        if (typeof(T) == typeof(SmallCar)) {
            objCar = new SmallCar();
        } else if (typeof(T) == typeof(MediumCar)) {
            objCar = new MediumCar();
        } else if (typeof(T) == typeof(BigCar)) {
            objCar = new BigCar();
        }
    
        return (T)objCar;
    }
    

    New-constraint:

    public T GetCar<T>()
        where T : ICar, new()
    {
        return new T();
    }
    
    0 讨论(0)
提交回复
热议问题