C#Generic Method,不能隐式转换

时间:2012-04-07 19:27:22

标签: c# generics methods

我有以下代码:

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

    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;
}

这是我得到的错误:Cannot implicitly convert type 'Test.Cars' to 'T'

我在这里错过了什么?所有汽车类型都实现了ICar界面。

由于

4 个答案:

答案 0 :(得分:9)

由于T在编译时未知,因此无法转换为T。 如果您希望让代码生效,可以将返回类型更改为ICar并删除通用T返回类型。

您也可以转发T。这也会奏效。 如果您只使用默认构造函数,则还可以在new()上使用new T()并使用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; } 来使代码生效。

样品

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;
}

角色:

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

新约束:

{{1}}

答案 1 :(得分:7)

您的代码是非法的,因为虽然您可能正在测试并知道您的给定T是BigCar或其他类型,但编译器无法提前知道,因此代码是非法的。根据您的用途,您可以

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

new()约束允许您在类型上调用默认(无参数)构造函数。

答案 2 :(得分:2)

您可以简化代码

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

答案 3 :(得分:0)

泛型是一个运行时概念。通用数据类型中使用的类型信息,无论其值或引用类型是否可以在运行时使用反射获取。

将带有T的代码编译到MSIL中时,它仅将其标识为具有类型参数。因此,泛型参数T在编译时未知。

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; }
}