使用 List<T> 属性 实现接口

Implementing interfaces with List<T> property

我有以下问题:

public interface IControlSingleContainer
{
   ControlCollection Content { get; set; }
}

public interface IControlCollectionContainer
{
    // I need to obtain a List of objects that implement IControlSingleContainer interface
    List<IControlSingleContainer> Items { get; set; }
}

public class TabItem : IControlSingleContainer
{
    public ControlCollection Content { get; set; }
}

public class TabbedContainer : IControlCollectionContainer
{
    public List<TabItem> Items { get; set; }  <- ERROR!
}

此代码期望 属性 TabbedContainer.Items 中的 List<IControlSingleContainer> 但我尝试使用包含对象的 Items 属性 创建 类实现 IControlSingleContainer.

已编辑:基本上,编译错误如下: 'Cosmo.UI.Controls.TabbedContainer' does not implement interface member 'Cosmo.UI.Controls.IControlCollectionContainer.Items'. 'Cosmo.UI.Controls.TabbedContainer.Items' can not implement' Cosmo.UI.Controls.IControlCollectionContainer.Items' because it has the kind of matching return value of 'System.Collections.Generic.List <Cosmo.UI.Controls. IControlSingleContainer>'.

我探索了一个具有通用接口但没有任何结果的解决方案...

你很接近,

 public class TabbedContainer : IControlCollectionContainer
    {
        public TabbedContainer()
        {
            Items = new List<IControlSingleContainer>();
            var t = new TabItem();
            Items.Add(t);
        }

        public List<IControlSingleContainer> Items { get; set; }
    }

不完全确定您在这里要做什么,但您不能将 List<interface> 强制转换为 List<concrete>。但是,您可以使您的界面通用并添加这样的约束:

public interface IControlCollectionContainer<T> where T : IControlSingleContainer
{
    List<T> Items { get; set; }
}

现在你的 class 定义变成这样:

public class TabbedContainer : IControlCollectionContainer<TabItem>
{
    public List<TabItem> Items { get; set; } 
}

这是 explicit interface implementations 存在的原因之一,具体取决于您的用例。

在您的情况下,您希望在直接使用 TabbedContainerItems 成为 TabItem。但是,该接口要求Items 是特定接口。

诀窍是同时声明 TabbedContainer.ItemsIControlCollectionContainer,但在幕后重复使用 TabItem class。

public class TabbedContainer : IControlCollectionContainer
{
    public List<TabItem> Items { get; set; } 

    List<IControlSingleContainer> IControlCollectionContainer.Items 
    { 
        get 
        { 
            return // Your actual tab items 
        }

        set 
        { 
             Items = //Whatever you need to do make sure you have actual
                     // TabItem objects
        }
    }
}

您需要更新上面的示例以实际处理 setting/getting 界面版本的项目,但主要思想是重用您的 TabItem 集合,以便它们始终保持同步。

这实际上是在您使用 TabbedContainer 并调用 Items 时,您将获得 TabItem 的列表,但是当您将实例作为 IControlCollectionContainer,你的 Items 将 return 你 IControlCollectionContainer.Items

请注意,这可能会变得相当复杂,具体取决于您如何 passing/modifying 容器实例。如果您不断通过 TabbedContainerIControlCollectionContainer 声明修改项目,则尝试让它们同步可能会很棘手。进行显式实现有时可以帮助您退后一步,重新准确评估您的最终目标是什么以及您在属性上声明的类型。

例如,如果您实际上并没有向界面列表中添加项目,那么为什么还要使用 List?作为 IEnumerable<T>IReadOnlyCollection<T>.

可能会更好