c#中Factory类中的泛型类型实例化

本文关键字:泛型类型 实例化 Factory | 更新日期: 2023-09-27 18:26:16

我有这个结构

public class Base<T>
{
}
public class A : Base<string>
{
}
public class B : Base<int>
{
}
public class Factory
{
    public Base<T> GetInstance<T>(int type)
    {
        if (type == 0)
            return new A();
        else
            return new B();
    }
}

但是我得到了关于Cannot convert expression type B to return type Base<T>的编译错误,为什么我得到这个错误?我该怎么修?

c#中Factory类中的泛型类型实例化

为什么我会出现这个错误?

出现此错误的原因是,当type0时,编译器无法在编译时验证Tstring,否则无法验证Tint。就编译器而言,T可以是任何类型。

我该怎么修?

您需要将结果强制转换为Base<T>,如下所示:

public class Factory
{
    public Base<T> GetInstance<T>(int type)
    {
        if (type == 0)
            return new A() as Base<T>;
        else
            return new B() as Base<T>;
    }
}

如果T不是正确的类型,这将导致此方法返回null

如果T不是正确的类型,以下备选方案将引发InvalidCastException异常:

public class Factory
{
    public Base<T> GetInstance<T>(int type)
    {
        if (type == 0)
            return (Base<T>)(object)new A();
        else
            return (Base<T>)(object)new B();
    }
}

另一种可能适用于您的方法(取决于您的需求)是删除type参数,并完全依赖T来确定需要返回的对象类型。这里有一个例子:

public Base<T> GetInstance<T>()
{
    if (typeof(T) == typeof(string))
        return (Base<T>)(object)new A();
    else if(typeof(T) == typeof(int))
        return (Base<T>)(object)new B();
    throw new ArgumentException("Unsupported type T");
}

您的方法不是泛型的,因为您返回的是基于传入类型的非泛型类型(无论您使用的是类型代码还是实际类型代码)最多您可以定义传入类型和返回类型之间的关系:

public Base<T> GetInstance<T>()
{
    if (typeof(T) == typeof(int))
        return new A() as Base<T>;
    else if (typeof(T) == typeof(string))
        return new B() as Base<T>;
    throw new ArgumentException("Unsupported type: " + typeof(T).ToString());
}

但是,泛型方法中的类型检查和分支通常是一种代码气味。一个更安全的选择是采用不同的方法:

public Base<int> GetIntInstance()
{
    return new A();
}
public Base<string> GetStringInstance()
{
    return new B();
}

注意

  • 代码的行数是相同的(如果不计算括号,则会减少)
  • 调用语法几乎相同(GetIntInstanceGetInstance<int>
  • 不存在使用不受支持的泛型类型参数的风险