在C#中键入非泛型接口泛型成员实现的约束

时间:2010-02-13 21:23:34

标签: c# interface generics

假设我有这样的界面:

interface IAwesome
{
    T DoSomething<T>();
}

有没有办法用类型约束实现DoSomething方法?显然,这不起作用:

class IncrediblyAwesome<T> : IAwesome where T : PonyFactoryFactoryFacade
{
    public T DoSomething()
    {
        throw new NotImplementedException();
    }
}

这显然不起作用,因为这个DoSomething()不能完全满足IAwesome的合同 - 它只适用于类型参数T的所有可能值的子集。有没有办法让这项工作得不到一些“投下黑魔法”(如果答案是否定的话,这就是我最后要做的事情)?

老实说,我不认为这是可能的,但我想知道你们的想法。

编辑:相关界面为 System.Linq.IQueryProvider ,因此我无法修改界面本身。

3 个答案:

答案 0 :(得分:7)

不,这在设计上是行不通的,因为这意味着IAwesome的合同不会(完全)满足。

只要IncrediblyAwesome<T>实现IAwesome,就可以执行此操作:

IAwesome x = new IncrediblyAwesome<Something>()

显然,使用您的附加约束,这可能无效,因为IAwesome的用户无法知道对其施加的限制。

在您的情况下,我能想到的唯一解决方案是(进行运行时检查):

interface IAwesome { // assuming the same interface as in your sample
    T DoSomething<T>();
}

class IncrediblyAwesome<TPony> : IAwesome where TPony : PonyFactoryFactoryFacade {
    IAwesome.DoSomething<TAnything>() {
        return (TAnything)((object)DoSomething()); // or another conversion, maybe using the Convert class
    }

    public TPony DoSomething() {
        throw new NotImplementedException();
    }
}

答案 1 :(得分:2)

不会有这样的伎俩吗?

interface IAwesome<U>
{
    T DoSomething<T>() where T : U
}

class IncrediblyAwesome<T> : IAwesome<PonyFactoryFactoryFacade>
{
    public T DoSomething()
    {
        throw new NotImplementedException();
    }
}

我不确定这是否会编译。

答案 2 :(得分:1)

正如您已经提到的,这样的解决方案不起作用。

此外,您的示例以另一种方式违反了合同:IncrediblyAwesome的一个实例始终绑定到PonyFactoryFactoryFacade的一个特定后代(顺便说一句,我真的 对这堂课的目的感兴趣:-))。因此,DoSomething的具体实现 not 是接口中指定的泛型方法,但始终返回一种类型。你不能写:

IAwesome a = new IncrediblyAwesome<SomePonyFacadeFactory1>();
SomePonyFacadeFactory2 facade2 = a.DoSomething<SomePonyFacadeFactory2>();

即使两个门面工厂都来自PonyFactoryFactoryFacade ......

另一个评论:我会远离黑魔法铸造,因为这个问题是你设计所固有的,而不仅仅是C#的缺点......