错误:"The type cannot be used as type parameter in the generic type of method."这可以通过约束或强制转换来解决吗?



我在与工厂进行实验时遇到了编译错误。这不是我会使用的实际工厂实现,因为我可能会在实际代码中使用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'.

以下是示例代码的重要部分:

public static class UniversalFactory
{
// New factories should be added here.
private static readonly IFactory<IFoo> FooFactoryEx;
private static readonly IFactory<IBar> BarFactoryEx;
static UniversalFactory()
{
// These bindings could also be provided via a DI framework like Ninject.
FooFactoryEx = new FooFactory();
BarFactoryEx = new BarFactory();
}
// Maps concrete objects to factories according to the interface(s) they implement.
public static TConcreteType Create<TConcreteType>(int id)
{
if (typeof(TConcreteType).IsAssignableFrom(typeof(IFoo)))
return FooFactoryEx.Create<TConcreteType>(id);
if (typeof(TConcreteType).IsAssignableFrom(typeof(IBar)))
return BarFactoryEx.Create<TConcreteType>(id);
return default(TConcreteType);
}
}

上面的测试代码看起来像:

public class TestClass
{
public void TestMain()
{
var foo1 = UniversalFactory.Create<FooImpl>(1);
var foo2 = UniversalFactory.Create<FooImpl>(2);
var bar1 = UniversalFactory.Create<BarImpl>(1);
}
}

错误似乎是,对于这一行,TConcreteType必须限制为IFoo:

return FooFactoryEx.Create<TConcreteType>(id);

同时(不可能)限制为该线路的IBar:

return BarFactoryEx.Create<TConcreteType>(id);

然而,我本以为这会在没有限制的情况下工作,因为我可以进行类型检查,例如:

if (typeof(TConcreteType).IsAssignableFrom(typeof(IFoo)))

然而,再多的约束或类型转换都无法解决这种情况。我是想做一些不可能的事情,还是编译器错误隐含了一个我还没有尝试过的明显约束?

编辑#1:我应该指出"FooImpl:IFoo"one_answers"BarImpl:IBar"。

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

public interface IFactory<in TFactoryType>
{
TConcreteType Create<TConcreteType>(int id) where TConcreteType : TFactoryType;
}

如果您无法理解此错误的来源,您应该尝试执行编译器所做的操作-用实际类型替换泛型。以下是在TConcreteTypeFooImpl:的情况下的情况

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

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

不确定问题。这很好用。

https://gist.github.com/trbngr/8911315

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

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

相关内容

最新更新