假设我有这样的界面:
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 ,因此我无法修改界面本身。
答案 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#的缺点......