简体   繁体   English

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

[英]Generic type instantiation in Factory class in c#

I have this structure 我有这个结构

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

but I get compile error about Cannot convert expression type B to return type Base<T> , why I get this error? 但我收到编译错误Cannot convert expression type B to return type Base<T> ,为什么我收到此错误? and how can I fix it? 我该如何解决?

why I get this error? 为什么我会收到此错误?

You are getting this error because the compiler cannot verify at compile time that T is string when type is 0 or that T is int otherwise. 您收到此错误是因为编译器无法在编译时验证Tstringtype0T是否则为int As far as the compiler is concerned, T could be any type. 就编译器而言, T可以是任何类型。

and how can I fix it? 我该如何解决?

You need to cast the result to Base<T> like this: 您需要将结果转换为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>;
    }
}

Which will cause this method to return null if T is not the correct type. 如果T不是正确的类型,这将导致此方法返回null

The following alternative will throw a InvalidCastException exception if T is not the correct type: 如果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();
    }
}

Another approach that might work for you (depending on your requirements) is to remove the type parameter and to depend completely on T to determine the type of object that you need to return. 另一种可能适合您的方法(取决于您的要求)是删除type参数并完全依赖于T来确定您需要返回的对象类型。 Here is an example: 这是一个例子:

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

Your method is not generic because you're returning a non-generic type based on the type that's passed in (whether you use a code for the type or the actual type). 您的方法不是通用的,因为您根据传入的类型返回非泛型类型(无论您是使用类型的代码还是实际类型)。 At best you could define a relationship between the type passed in and the return type: 最好你可以定义传入的类型和返回类型之间的关系:

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

But type checking and branching in a generic method is generally a code smell. 但是,通用方法中的类型检查和分支通常是代码气味。 A safer option would be to have different methods: 更安全的选择是使用不同的方法:

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

Note that 注意

  • The number of lines of code is the same (less if you don't count brackets) 代码行数相同(如果不计算括号,则更少)
  • The calling syntax is almost identical ( GetIntInstance vs GetInstance<int> ) 调用语法几乎相同( GetIntInstance vs GetInstance<int>
  • There is no risk of using an unsupported generic type argument 不存在使用不受支持的泛型类型参数的风险

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM