我正在尝试调用一个类似于以下定义的方法(简化以避免混淆):
public static void Register<T>(T value) where T : BaseClass, IInterface
只要我有一个定义这两个值的类实例,这就可以正常工作。当我将`BaseClass'传递给方法然后尝试在上面的声明中使用该实例时,会出现问题。例如:
public class MyClass
{
public MyClass(BaseClass value)
{
Register(value);
}
}
我可以将实现BaseClass和IInterface的类的实例和实例传递给构造函数,但是当我尝试在Register
方法中使用该值时,我得到一个编译错误说明:
类型'BaseClass'不能在泛型类型或方法'Register(T)'中用作类型参数'T'。没有从'BaseClass'到'IInterface'的隐式引用转换。
如果我像这样更改构造函数中的类型:
public class MyClass
{
public MyClass(IInterface value)
{
Register(value);
}
}
我收到错误声明:
类型'IInterface'不能用作泛型类型或方法'Register(T)'中的类型参数'T'。没有从“IInterface”到“BaseClass”的隐式引用转换。
这看起来有点像22。 有没有办法可以定义参数来表明它必须同时实现BaseClass和IInterface?
答案 0 :(得分:6)
当我写这个问题时,我想出了答案,并认为我会发布它而不是删除问题。
我只需要重新定义课程:
public class MyClass<T> where T : BaseClass, IInterface
{
public MyClass(T value)
{
Register(value);
}
}
答案 1 :(得分:1)
Matt给出的解决方案是一个简单的答案,适用于不需要将传入的对象存储在字段或集合中的情况。如果你需要持久保存传入的对象,事情就会变得更加更多。对SomeClass<T>
满足多个约束的T
来说,存储类T的项并将它们作为泛型传递给具有此类约束的例程,但是如果类具有方法{{1}则很容易}} SomeMethod<TParam>(TParam thing)
,它不会有TParam:IFoo,BaseBar
类型的任何字段。它可以将TParam
存储到thing
或IFoo
类型的字段中,但除非BaseBar
实现BaseBar
,否则所有传入的实例都将从实现IFoo
的一个特定BaseBar
衍生物,没有办法指定字段的类型将满足两个约束(如果每个实例都派生自一个特定的IFoo
实现BaseBar
的导数,可以简单地将该类型用作单个约束,或者根本不用泛型 - 只需将其用作参数类型)。
有很多方法可以解决这些问题,使用Reflection,我称之为IFoo
的接口模式,或者一些棘手的嵌套回调接口。但是,在某些情况下,最好为采用双约束参数的方法提供替代方法(让方法采用一种约束类型的参数,将其转换为另一种类型,并接受缺乏编译时的安全性)