-4 .net c# generics typing covariance
注意:请不要在当前状态下重视此问题.一旦我能够解决我的潜在问题,我就会意识到我会很难重新解释这个问题,以真正反映出它的动机和决议是什么.Anwyay,我将在接下来的几天里尝试对其进行改写,以便它对未来的访问者有用,并且回答者可能有机会调整答案.即使是我的自动回答也没有反映出这个问题,所以它对社区有用......
假设我有一个这样的界面:
public interface IHasMany<T>
{
ISet<T> Items { get; }
}
Run Code Online (Sandbox Code Playgroud)
一个类实现如下:
public class X : IHasMany<IWhatever>
{
public ISet<Whatever> Whatevers { get; } = new HashSet<Whatever>();
ISet<IWhatever> IHasMany<IWhatever>.Items { get; }
}
Run Code Online (Sandbox Code Playgroud)
由于集合泛型类型不能协变(我理解为什么它被设计阻止的背景),所以没有简单的路径可以同时公开一组给定的接口实现和一组与接口同时输入的相同实现.
为了找到一个理想情况下我不需要实现某种同步或更改跟踪来维护两个不同集合的解决方案,我正在摸不着头脑......
请注意,IHasMany<T>.Items必须仍然可写,否则就像键入它一样容易IEnumerable<IWhatever>并继续前进......
C#不会阻止你的集合变成协变,因为C#团队并不打算弄清楚如何实现它.相反,它在C#中是不可能的,因为它在概念上是不可能的.您根本无法将其ISet<Whatever>视为一个ISet<IWhatever>因为您可以将项目添加到非ISet<IWhatever>类型的项目中Whatever,并且如果实际对象是a ISet<Whatever>,则不允许添加非类型的项目Whatever.
你可以拥有一个类型的属性IReadOnlySet<IWhatever>并使其变得协变,但是因为你想拥有一个可变的集合,所以没有办法让它工作.你必须让你的实际底层集合成为一组IWhatever对象,或者具有X实现IHasMany<Whatever>而不是IHasMany<IWhatever>,因为它只是你真正希望它实现的前者合约,而不是后者.