2

我正在尝试调用具有类似于以下定义的方法(为避免混淆而进行了简化):

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?

4

2 回答 2

7

当我写这个问题时,我想出了答案,并认为我会发布它而不是删除问题。

我只需要重新定义类:

public class MyClass<T> where T : BaseClass, IInterface
{
    public MyClass(T value)
    {
        Register(value);
    }
}
于 2012-12-06T16:55:24.303 回答
1

对于不需要将传入的对象存储在字段或集合中的情况,Matt 给出的解决方案是一个简单的答案。如果您需要持久化传入的对象,事情会变得更加困难。SomeClass<T>where很容易T满足多个约束,存储类 T 的项目并将它们作为泛型传递给具有此类约束的例程,但是如果一个类具有SomeMethod<TParam>(TParam thing)where方法TParam:IFoo,BaseBar,它将没有任何 type 字段TParam。它可以存储到orthing类型的字段中,但除非implements ,或者所有传入的实例都将派生自一个特定的派生类,该派生类实现IFooBaseBarBaseBarIFooBaseBarIFoo, 没有办法指定一个字段的类型将同时满足这两个约束(如果每个实例都派生自一个BaseBar实现的特定派生IFoo,则可以简单地将该类型用作单个约束,或者就此而言根本不关心泛型 - 只是使用它作为参数类型)。

有一些方法可以解决这些问题,要么使用反射,我称之为接口模式,要么使用ISelf<T>一些棘手的嵌套回调接口。但是,在某些情况下,最好为采用双重约束参数的方法提供替代方案(让方法采用一种约束类型的参数,将其转换为另一种类型,并接受缺乏编译时安全性) .

于 2012-12-06T19:21:37.230 回答