Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c中工厂类中的泛型类型实例化#_C#_.net_Generics - Fatal编程技术网

C# c中工厂类中的泛型类型实例化#

C# c中工厂类中的泛型类型实例化#,c#,.net,generics,C#,.net,Generics,我有这个结构 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 ne

我有这个结构

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();
    }
}
公共类基
{
}
公共A类:基本类
{
}
B类公共服务:基本服务
{
}
公营工厂
{
公共基GetInstance(int类型)
{
如果(类型==0)
返回新的A();
其他的
返回新的B();
}
}
但是我得到了关于
的编译错误,无法将表达式类型B转换为返回类型Base
,为什么我会得到这个错误?我怎样才能修好它

为什么我会犯这个错误

出现此错误是因为当
类型
0
时,编译器无法在编译时验证
T
是否为
string
,或者
T
是否为
int
。就编译器而言,
T
可以是任何类型

我怎样才能修好它

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

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>;
    }
}
另一种可能适合您的方法(取决于您的需求)是删除
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 GetInstance()
{
if(typeof(T)=typeof(string))
返回(基)(对象)新的A();
否则如果(typeof(T)=typeof(int))
返回(基本)(对象)新B();
抛出新ArgumentException(“不支持的类型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 GetInstance()
{
if(typeof(T)=typeof(int))
返回新的A()作为基函数;
else if(typeof(T)=typeof(string))
返回新的B()作为基函数;
抛出新的ArgumentException(“不支持的类型:+typeof(T).ToString());
}
但泛型方法中的类型检查和分支通常是一种代码味道。更安全的选择是采用不同的方法:

public Base<int> GetIntInstance()
{
    return new A();
}
public Base<string> GetStringInstance()
{
    return new B();
}
public Base GetIntInstance()
{
返回新的A();
}
公共基GetStringInstance()
{
返回新的B();
}
注意

  • 代码行数相同(如果不计算括号,则更少)
  • 调用语法几乎相同(
    GetIntInstance
    vs
    GetInstance
  • 不存在使用不受支持的泛型类型参数的风险

可以显示调用工厂的代码吗?这不起作用,因为
A
B
不是从相同的基类型派生的(除了
Object
),因为
base
base
在继承层次结构中是不相关的(除了作为相同的基类共享
Object
);据我所知,这无法直接修复。您的代码不是泛型的-您返回的是基于特定输入的特定类型,与该类型无关。泛型的要点是使用客户机选择的任何类型(受定义的约束)。@StephenBrickner这是编译时错误,虽然这可能在语法上起作用(因此+1),但我看不出它的要点;调用方必须明确知道所需的类型,因此工厂不会提供真正的抽象。是否可以使用约束来指导编译器
where T:Base
(不知道怎么做)?@Codor,我只是简单地向OP解释编译器为什么抱怨,并给他一个如何修复它的直接答案。@Sinatr,我认为你做不到that@Codor,这就是我直接回答的原因。我们不知道OP到底想要什么,直到他对答案发表评论:)
public Base<int> GetIntInstance()
{
    return new A();
}
public Base<string> GetStringInstance()
{
    return new B();
}