IList在c#中使用协变和逆变,这可能吗?

发布于 2024-08-01 23:45:42 字数 346 浏览 4 评论 0原文

这可能吗? (我没有 vs. 2010,所以我无法自己尝试,抱歉)

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    public IEnumerator<TOutput> GetEnumerator();
    public void Add(TInput item);
}

public interface IList<T> : IComplexList<T, T>
{
}

如果我做对了,您可以使用它在同一接口中实际实现协变和逆变。

would this be possible? (I don't have vs. 2010, so I can't try it myself, sorry)

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    public IEnumerator<TOutput> GetEnumerator();
    public void Add(TInput item);
}

public interface IList<T> : IComplexList<T, T>
{
}

If I get it right, you could use this to actually implement covariance and contravariance in the same interface.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不醒的梦 2024-08-08 23:45:42

好吧,由于现有的 IList 类型,您的问题有点令人困惑。 但是,以下确实可以编译:

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    IEnumerator<TOutput> GetEnumerator();
    void Add(TInput item);
}

public interface ISimpleList<T> : IComplexList<T, T>
{
}

您甚至可以更改它以扩展IEnumerable

public interface IComplexList<out TOutput, in TInput>
    : IEnumerable<TOutput>
    where TOutput : TInput
{        
    void Add(TInput item);
}

public interface ISimpleList<T> : IComplexList<T, T>
{
}

索引器很棘手,因为您需要涉及不同的类型。 您可以这样做:

TOutput Get(int index);
void Set(int index, TInput item);

然后将索引器放入 ISimpleList 而不是当然...

但这并不能让您以不同方式使用 ISimpleList ,因为您基本上强制 TInput=TOutput。

另一种方法是将输入与输出分开:

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> {}

然后您可以编写:

public void Foo(IWritableList<string> x) { ... }

IMyList<object> objects = new MyList<object>();
Foo(objects);

对于 IReadableList 反之亦然。 换句话说,您允许每一方单独存在差异,但永远不会同时获得两侧的差异。

Well, your question is slightly confusing because of the existing IList<T> type. However, the following does compile:

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    IEnumerator<TOutput> GetEnumerator();
    void Add(TInput item);
}

public interface ISimpleList<T> : IComplexList<T, T>
{
}

You can even change it to extend 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>
{
}

The indexer is tricky, because you'd want different types involved. You could do:

TOutput Get(int index);
void Set(int index, TInput item);

and then put the indexer into ISimpleList<T> instead of course...

That doesn't let you use ISimpleList<T> variantly though, because you've basically forced TInput=TOutput.

An alternative approach is to separate out the input from the output:

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> {}

Then you could write:

public void Foo(IWritableList<string> x) { ... }

IMyList<object> objects = new MyList<object>();
Foo(objects);

and vice versa for IReadableList. In other words, you allow variance for each side individually, but you never get variance for the two sides together.

知足的幸福 2024-08-08 23:45:42

不,你不能。 在您的示例中 IList 是不变的。 IList 需要将 in/out 声明为协变/逆变。 仅通过继承一些协变的接口是不可能做到这一点的。

No, you can't. In your example IList<T> is invariant. IList<T> would require to declare in/out to be covariant/contravariant. It's not possible to do that just by inheriting some interface that is covariant.

如梦亦如幻 2024-08-08 23:45:42

如果读写属性的实现也被视为只读属性的实现,则可以通过从 IReadableList(of Out T) 和 IAddableList(的 T)。 假设这些接口在定义之前仅包含 IList(Of T) 中存在的成员,则实现 IList(Of T) 的代码将自动实现这些其他成员。 不幸的是,要使 IReadableList 协变,它必须具有只读索引器属性; IList 中读写属性的实现无法替代。 因此,让 IList(Of T) 从可用的 IReadableList(Of Out T) 继承将破坏 IList(Of T) 的所有实现。

If an implementation of a read-write property were also considered an implementation of a read-only property, one could add a useful form of List covariance and contravariance by having IList(of T) derive from IReadableList(of Out T) and IAddableList(of In T). Provided that those interfaces simply included members that were present in IList(Of T) before they were defined, code which implemented IList(Of T) would automatically implement those other members. Unfortunately, for IReadableList to be covariant, it would have to have a read-only indexer property; the implementation of the read-write property in IList could not be substituted. Having IList(Of T) inherit from a usable IReadableList(Of Out T) would thus break all implementations of IList(Of T).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文