简体   繁体   English

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

[英]Type constraints on implementations of generic members of non-generic interfaces in C#

Let's say I have an interface like that: 假设我有一个这样的界面:

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

Is there any way to implement the DoSomething method with type constraint? 有没有办法用类型约束实现DoSomething方法? Obviously, this won't work: 显然,这不起作用:

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

This obviously won't work because this DoSomething() won't fully satisfy the contract of IAwesome - it only work for a subset of all possible values of the type parameter T. Is there any way to get this work short of some "casting black magic" (which is what I'm going to do as last resort if the answer is no)? 这显然是行不通的,因为这个DoSomething()不能完全满足IAwesome的合同 - 它只适用于类型参数T的所有可能值的子集。有没有办法使这个工作缺少一些“铸造”黑魔法“(如果答案是否定的话,这就是我最后要做的事情)?

Honestly, I don't think it's possible but I wonder what you guys think. 老实说,我不认为这是可能的,但我想知道你们的想法。

EDIT : The interface in question is System.Linq.IQueryProvider so I can't modify the interface itself. 编辑 :有问题的接口是System.Linq.IQueryProvider所以我无法修改接口本身。

No, this cannot work by design, since it would mean that the contract for IAwesome would not be (fully) satisfied. 不,这在设计上是行不通的,因为这意味着IAwesome的合同不会(完全)满足。

As long as IncrediblyAwesome<T> implements IAwesome , one is allowed to do this: 只要IncrediblyAwesome<T>实现IAwesome ,就可以执行此操作:

IAwesome x = new IncrediblyAwesome<Something>()

Obviously, with your additional constraint, this could not work, since the user of IAwesome cannot know of the restrictions put on it. 显然,使用您的附加约束,这可能无法工作,因为IAwesome的用户无法知道对其施加的限制。

In your case, the only solution I can think of is this (doing runtime checking): 在您的情况下,我能想到的唯一解决方案是(进行运行时检查):

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

Wouldn't something like this do the trick? 难道不会有这样的伎俩吗?

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

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

I'm not sure if this compiles. 我不确定这是否会编译。

As you've already mentioned, such a solution cannot work. 正如您已经提到的,这样的解决方案无法工作。

Moreover, your example violates the contract in another way: One instance of IncrediblyAwesome is always bound to one specific descendant of PonyFactoryFactoryFacade (btw, I'd be really interested in the purpose of this class :-)). 此外,你的例子以另一种方式违反了合同: IncrediblyAwesome一个实例总是绑定到PonyFactoryFactoryFacade一个特定后代(顺便说一句,我真的对这个类的目的感兴趣:-))。 Therefore, the concrete implementation of DoSomething would not be a generic method as specified in the interface, but always return one single type. 因此, DoSomething的具体实现不是接口中指定的泛型方法,而是始终返回单个类型。 You couln't write: 你不能写:

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

even though both facade-factories decend from PonyFactoryFactoryFacade ... 即使两个门面工厂都来自PonyFactoryFactoryFacade ......

Another comment: I would stay away from black magic casting, since this problems are inherent to your design and not just a shortcoming of C# ... 另一个评论:我会远离黑魔法铸造,因为这个问题是你设计所固有的,而不仅仅是C#的缺点......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM