Vâng, câu hỏi của bạn hơi khó hiểu do loại IList<T>
hiện tại. Tuy nhiên, sau không biên dịch:
public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
IEnumerator<TOutput> GetEnumerator();
void Add(TInput item);
}
public interface ISimpleList<T> : IComplexList<T, T>
{
}
Bạn thậm chí có thể thay đổi nó để mở rộng IEnumerable<TOutput>
:
public interface IComplexList<out TOutput, in TInput>
: IEnumerable<TOutput>
where TOutput : TInput
{
void Add(TInput item);
}
public interface ISimpleList<T> : IComplexList<T, T>
{
}
Các indexer là khó khăn, bởi vì bạn muốn loại khác nhau có liên quan. Bạn có thể làm:
TOutput Get(int index);
void Set(int index, TInput item);
và sau đó đặt indexer vào ISimpleList<T>
thay vì tất nhiên ...
Đó không cho phép bạn sử dụng ISimpleList<T>
variantly mặc dù, bởi vì bạn đã cơ bản buộc TInput = TOutput.
Một phương pháp khác là để tách ra các đầu vào từ đầu ra:
public interface IReadableList<out T> : IEnumerable<T>
{
T Get(int index);
}
public interface IWritableList<in T>
{
void Add(T item);
void Set(int index, T item);
}
public interface IMyList<T> : IReadableList<T>, IWritableList<T> {}
Sau đó, bạn có thể viết:
public void Foo(IWritableList<string> x) { ... }
IMyList<object> objects = new MyList<object>();
Foo(objects);
và ngược lại cho IReadableList
. Nói cách khác, bạn cho phép phương sai cho mỗi bên riêng lẻ, nhưng bạn không bao giờ có được phương sai cho hai bên với nhau.
Nó chắc chắn không biên dịch nhưng nó sẽ không được đồng/contra-biến thể. Không thể sử dụng 'ISimpleList' làm 'ISimpleList
Cảm ơn bạn đã cố gắng –
Tôi sẽ cập nhật câu trả lời của mình để cụ thể hơn - xin lỗi, vẫn đang suy nghĩ tất cả điều này thông qua. –