强制转换一般收集项目类型

时间:2018-10-19 20:00:59

标签: c#

以下代码说明了我遇到的情况。实际的代码使用不同的名称并以其他方式获取值,但它们与我需要的答案匹配。特别是在第76-89行(我控制的仅有的几行)中,我需要提取带有值的“ ICollection”类型的变量,而且我不喜欢使用的任何方法。有没有创建类“ AbstractCollection”的另一种方法?

namespace ConsoleApp1
{
    using System.Collections.Generic;
    using System.Linq;

    interface IEntity
    {
        string Id { get; }
        string Name { get; }
    }

    class Entity : IEntity
    {
        public Entity(string id, string name)
        {
            Id = id;
            Name = name;
        }
        public string Id { get; }
        public string Name { get; }
    }

    interface ICollection<TGeneric>
    {
        IEnumerable<TGeneric> Items { get; }
    }

    class Collection<TGeneric> : ICollection<TGeneric> where TGeneric : Entity, IEntity
    {
        public IEnumerable<TGeneric> Items { get; set; }
    }

    class AbstractCollection<TConcrete, TAbstract> : ICollection<TAbstract> where TAbstract : class, IEntity
    {
        public AbstractCollection(ICollection<TConcrete> collection)
        {
            this._Items = new List<TAbstract>();
            if (collection?.Items != null)
            {
                foreach (TConcrete concreteItem in collection.Items)
                {
                    TAbstract abstractItem = concreteItem as TAbstract;
                    this._Items.Add(abstractItem);
                }
            }
        }
        public IEnumerable<TAbstract> Items
        {
            get { return this._Items; }
            set { this._Items = value?.ToList(); }
        }
        private IList<TAbstract> _Items { get; set; }
    }

    class EntityCollection : Collection<Entity>
    {
        public EntityCollection()
        {
            var items = new List<Entity>()
            {
                new Entity("1", "Name1"),
                new Entity("2", "Name2"),
                new Entity("3", "Name3")
            };
            Items = items;
        }
    }

    class Context
    {
        public Context()
        {
            var concreteItems = new EntityCollection();
            // I can modify from this line to the end of the method but not any code before.
            // I expected values in "list1" but is null.
            var list1 = concreteItems as ICollection<IEntity>;
            var list2 = concreteItems as ICollection<Entity>;
            var abstractItems = new List<IEntity>();
            foreach (Entity concreteItem in concreteItems.Items)
            {
                IEntity abstractItem = concreteItem as IEntity;
                abstractItems.Add(abstractItem);
            }
            // Why "list3" is null?
            var list3 = abstractItems as ICollection<IEntity>;
            // I want to avoid class "AbstractCollection"
            var list4 = new AbstractCollection<Entity, IEntity>(list2);
            // Finally "list5" has value in the way I want it.
            var list5 = list4 as ICollection<IEntity>;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var context = new Context();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

该解决方案的协方差指南:

interface ICollection<out TGeneric>
{
    IEnumerable<TGeneric> Items { get; }
}