C# 错误:";该类型不能用作方法的泛型类型中的类型参数。”;这可以通过约束或强制转换来解决吗?

C# 错误:";该类型不能用作方法的泛型类型中的类型参数。”;这可以通过约束或强制转换来解决吗?,c#,generics,types,C#,Generics,Types,我在进行工厂实验时遇到了一个编译错误。这不是我将使用的实际工厂实现,因为我可能会在实际代码中使用DI系统。我想提前说明这一点,因为我不是在寻求帮助 下面的代码片段让我感到困惑的是如何约束Create()方法,以便可以返回多个类型。编译器错误为: The type 'TConcreteType' cannot be used as type parameter 'TConcreteType' in the generic type or method 'Tests.IFactory<TFac

我在进行工厂实验时遇到了一个编译错误。这不是我将使用的实际工厂实现,因为我可能会在实际代码中使用DI系统。我想提前说明这一点,因为我不是在寻求帮助

下面的代码片段让我感到困惑的是如何约束Create()方法,以便可以返回多个类型。编译器错误为:

The type 'TConcreteType' cannot be used as type parameter 'TConcreteType'
in the generic type or method 'Tests.IFactory<TFactoryType>.Create<TConcreteType>(int)'.
There is no boxing conversion or type parameter conversion from 'TConcreteType' to 
'Tests.IFoo'.
但是,再多的约束或类型转换都不能解决这种情况。我是在尝试做一些不可能的事情,还是编译器错误隐含了一个明显的约束,而我还没有尝试

编辑#1:我应该指出“FooImpl:IFoo”和“BarImpl:IBar”

编辑#2:此信息是为Chris Martin添加的,因为我在示例中遗漏了一个重要的类型约束:

public interface IFactory<in TFactoryType>
{
    TConcreteType Create<TConcreteType>(int id) where TConcreteType : TFactoryType;
}
公共接口IFactory
{
TConcreteType创建(int id),其中TConcreteType:TFactoryType;
}

据我所知,typeof返回一些完全不同的数据类型,这些数据类型只告诉我们什么是类。两个typeof应该具有相同的数据类型,即使它们请求的是两个完全不相关的类的typeof


我认为你需要做的是让TConcreteType实现IFoo和IBar接口。

如果你在理解这个错误的来源方面有困难,你应该尝试编译器所做的事情——用实际的类型替换泛型。以下是
tcontextype
FooImpl
时的情况:

public static FooImpl Create(int id)
{
    if (typeof(FooImpl).IsAssignableFrom(typeof(IFoo)))
    //"where FooImpl : IFoo", returns FooImpl, looks fine
        return FooFactoryEx.Create<FooImpl>(id);
    if (typeof(FooImpl).IsAssignableFrom(typeof(IBar)))
    //"where FooImpl : IBar". Wait... what?
        return BarFactoryEx.Create<FooImpl>(id);
    return default(FooImpl);
}
publicstaticfooimplcreate(int-id)
{
if(typeof(FooImpl).IsAssignableFrom(typeof(IFoo)))
//返回FooImpl的“where FooImpl:IFoo”看起来不错
返回foodfactoryex.Create(id);
if(typeof(FooImpl).IsAssignableFrom(typeof(IBar)))
//“IBar在哪里”,等等…什么?
返回BarFactoryEx.Create(id);
返回默认值(FooImpl);
}

没有多大意义,是吗?编译器无法知道
BarFactoryEx.Create(id)从不执行。除非您愿意从
IFactory.Create()
或深入动态代码生成:)中删除类型约束,否则无法绕过该限制。总的来说,我认为您最初的方法更好(
UniversalFactory.FooFactory.Create()

不确定这个问题。这个很好用


如果使用“where tcontcrete Type:IFoo,IBar”将tcontcrete Type约束为两行,则这两行将继续失败,因为IFoo和IBar不相互实现。测试的目的是查看是否可以传入一个具体类型,比如FooImpl,并使用一个方法将其映射到一个工厂,该工厂处理FooImpl实现的任何接口,并使用该工厂进行创建。我试图做的事情是不可能的吗?如果是,从技术角度来说,为什么?同意。我在昨天的一次谈话中得出了同样的结论。最初的方法也稍微不那么“聪明”,尽管整个想法对于实际使用来说可能太“聪明”了。我在OP中为您添加了一个编辑,因为我的示例中缺少了一个片段。尼基塔·布里扎克也抓到了这个。我有一个额外的类型安全约束,它破坏了我的测试。哎呀。
return FooFactoryEx.Create<TConcreteType>(id);
return BarFactoryEx.Create<TConcreteType>(id);
if (typeof(TConcreteType).IsAssignableFrom(typeof(IFoo)))
public interface IFactory<in TFactoryType>
{
    TConcreteType Create<TConcreteType>(int id) where TConcreteType : TFactoryType;
}
public static FooImpl Create(int id)
{
    if (typeof(FooImpl).IsAssignableFrom(typeof(IFoo)))
    //"where FooImpl : IFoo", returns FooImpl, looks fine
        return FooFactoryEx.Create<FooImpl>(id);
    if (typeof(FooImpl).IsAssignableFrom(typeof(IBar)))
    //"where FooImpl : IBar". Wait... what?
        return BarFactoryEx.Create<FooImpl>(id);
    return default(FooImpl);
}