首先,我要说的是,设计审查肯定已经开始。原始的Java类聚集一个
IGeneric1<?>成员,但是在不知道其类型参数的情况下,不可能以
method1WithParam类型安全的方式对其进行调用。
这意味着elem只能用于调用其
method1成员,该成员的签名不依赖于的类型参数
IGeneric1。因此,method1可以将其分解为一个非通用接口:
// C# pre:interface INotGeneric1 { void method1<T>(IGeneric2<T> val) where T : Impl;}interface IGeneric1<T> : INotGeneric1 where T : Impl { T method1WithParam(T to);}之后,class Generic2可以聚合INotGeneric1成员:
abstract class Generic2<T>: IGeneric2<T> where T : Impl{ protected INotGeneric1 elem; // It's highly likely that you would want to change the type of val // to INotGeneric1 as well, there's no obvious reason to require an // IGeneric1<U> public void method2<U>(IGeneric1<U> val) where U : Impl { elem = val; // this is now OK }}当然,现在,elem.method1WithParam除非您诉诸强制转换或反射,否则就无法调用,即使已知存在这样的方法并且该方法是通用的,并且带有一些未知类型X作为类型实参。但是,这与Java代码的限制相同。只是C#编译器不会接受此代码,而Java仅在您尝试调用时才会抱怨method1WithParam1。



