(制限付きの)ワイルドカードジェネリックを使用するJavaコードをC#に変換しようとして立ち往生しています。私の問題は、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>'.
提案?
[やや難しいシナリオについては、フォローアップの質問も参照してください]