Tôi đang cố gắng dịch một số mã Java sử dụng các ký tự đại diện wildcard (bounded) thành C#. Vấn đề của tôi là, Java dường như cho phép một kiểu generic là cả hai biến thể và contravariant khi được sử dụng với một ký tự đại diện..NET tương đương với Java wildcard (IInterf <?>)?
[Đây là một spin-off từ trước question đối phó với một trường hợp đơn giản của giáp-wildcard]
Java - hoạt động:
class Impl { }
interface IGeneric1<T extends Impl> {
void method1(IGeneric2<?> val);
T method1WithParam(T val);
}
interface IGeneric2<T extends Impl> {
void method2(IGeneric1<?> val);
}
abstract class Generic2<T extends Impl> implements IGeneric2<T> {
// !! field using wildcard
protected IGeneric1<?> elem;
public void method2(IGeneric1<?> val1) {
val1.method1(this);
//assignment from wildcard to wildcard
elem = val1;
}
}
abstract class Generic<T extends Impl> implements IGeneric1<T>, IGeneric2<T> {
public void method1(IGeneric2<?> val2) {
val2.method2(this);
}
}
C# - không biên dịch ...
class Impl { }
interface IGeneric1<T> where T:Impl {
//in Java:
//void method1(IGeneric2<?> val);
void method1<U>(IGeneric2<U> val) where U : Impl; //see this Q for 'why'
// https://stackoverflow.com/a/14277742/11545
T method1WithParam(T to);
}
interface IGeneric2<T>where T:Impl {
void method2<U>(IGeneric1<U> val) where U : Impl;
}
abstract class Generic2<T, TU>: IGeneric2<T> //added new type TU
where T : Impl
where TU : Impl
{
//in Java:
//protected IGeneric1<?> elem;
protected IGeneric1<TU> elem;
//in Java:
//public void method2(IGeneric1<?> val1)
public void method2<U>(IGeneric1<U> val)
where U : TU //using TU as constraint
{
elem = val; //Cannot convert source type 'IGeneric1<U>'
//to target type 'IGeneric1<TU>'
}
public abstract void method1WithParam(T to);
}
abstract class Generic<T> : IGeneric1<T>, IGeneric2<T> where T : Impl
{
//in Java:
//public void method1(IGeneric2<?> val2)
public void method1<U>(IGeneric2<U> val2) where U : Impl
{
val2.method2(this);
}
public abstract T method1WithParam(T to);
public abstract void method2<U>(IGeneric1<U> val) where U : Impl;
public abstract void nonGenericMethod();
}
Nếu tôi thay đổi interface IGeneric1<T>
thành interface IGeneric1<out T>
các lỗi trên sẽ biến mất, nhưng method1WithParam(T)
phàn nàn về phương sai:
Parameter must be input-safe. Invalid variance: The type parameter 'T' must be
contravariantly valid on 'IGeneric1<out T>'.
Tôi không biết nhiều về Generics Java. Nhưng mã Java có an toàn không? – Euphoric
Bạn có thể vui lòng cung cấp mã Java sẽ được gọi hay không? Tôi vẫn thấy khó hiểu tại sao một người nào đó lại tạo nên một quái vật như vậy. – Euphoric
Lưu ý rằng các hạn chế về phương sai của C# được cố ý hạn chế hơn vì mục đích đơn giản. Nó hoàn toàn có thể là những gì bạn đang thể hiện trong mã Java đơn giản là không có một tương đương đơn giản trong C#. – millimoose