我一直在試圖將一些使用(有界)通配符泛型的Java代碼轉換爲C#。 我的問題是,Java似乎允許通用類型與通配符一起使用時是協變和逆變。例如:.NET等效於Java通配符泛型<?>具有同向和反向變化?
的Java:
interface IInterf { }
class Impl implements IInterf { }
interface IGeneric1<T extends Impl> {
void method1(IGeneric2<?> val);
void method1WithParam(T val);
}
interface IGeneric2<T extends Impl> {
void method2(IGeneric1<?> val);
}
abstract class Generic<T extends Impl> implements IGeneric1<T>, IGeneric2<T> {
public void method1(IGeneric2<?> val2) {
val2.method2(this);
}
}
...作品。 (?)
C#相當於
interface IInterf { }
class Impl : IInterf { }
interface IGeneric1<T> where T:Impl {
//Java was:
//void method1(IGeneric2<?> val2);
void method1(IGeneric2<Impl> val);
void method1WithParam(T to);
}
interface IGeneric2<T>where T:Impl {
void method2(IGeneric1<Impl> val);
}
abstract class Generic<T> : IGeneric1<T>, IGeneric2<T> where T : Impl
{
//Java was:
//public void method1(IGeneric2<?> val2) {
public void method1(IGeneric2<Impl> val2)
{
val2.method2(this); //'this': Argument type 'Generic<T>' is not
//assignable to parameter type 'IGeneric1<Impl>'
}
public abstract void method1WithParam(T to);
public abstract void method2(IGeneric1<Impl> val);
}
...無法編譯 - 看到錯誤的註釋。這是可以預料到的,因爲IGeneric的泛型參數沒有標記爲協方差的「out」。
如果我改變了:
interface IGeneric1<T> where T:Impl {
這個
interface IGeneric1<out T> where T:Impl
錯誤消失,但一個又一個的出現,爲方法的聲明採用相同的接口內的通用參數:
interface IGeneric1<T> where T:Impl {
void method1WithParam(T val); //Parameter must be input-safe.
//Invalid variance: The type parameter 'T' must be
//contravariantly valid on 'IGeneric1<out T>'.
建議?
[另見follow-up question了稍硬的場景]
什麼是Java中的尖括號內的問號是什麼意思? –
「任何類型都行」(或者在這種情況下,任何類型都來自'Impl')。它被稱爲「通配符」。 http://docs.oracle.com/javase/tutorial/extra/generics/wildcards。html –