【问题标题】:How to use the derived type in a generic collection from an abstract class (C#)?如何在抽象类 (C#) 的泛型集合中使用派生类型?
【发布时间】:2011-08-01 03:58:29
【问题描述】:

我有一个通用集合,其中包含集合中的项目需要调用的方法。每个项目都有对通用集合的引用。问题是我不能使用每个项目的类型作为传递给泛型集合的类型。

思路是这样的(我知道不会编译):

    public class MyCollection<T>
    {
        public void Call(T item) { ... }
    }

    public abstract class MyItemBase
    {
        protected MyCollection<typeof(this)> _collection;
        public MyItem(MyCollection<typeof(this)> collection)
        {
            this._collection = collection;
        }

        public DoSomething()
        {
            this._collection.Call(this);
        }
    }

    public class MyItem : MyItemBase
    {
    }

显然,您不能声明 MyCollection&lt;typeof(this)&gt;,但我认为通过这种方式编写它,您可以大致了解我想要做什么。本质上,我希望抽象类对集合的引用 mean MyCollection&lt;MyClass&gt;。

有什么办法可以做到吗?

【问题讨论】:

    标签: generics c#-4.0 collections types


    【解决方案1】:

    首先,为什么您的 ItemBase 类包含 ItemCollection?不应该反过来,你的 Collection 类应该包含 Items 吗?

    但是,对于您的问题上下文,如果您以这种方式设计您的课程,您可以保证类型安全:

     public class MyCollection<T> where T : MyItemBase<T>
    {
        public void Call(MyItemBase<T> item) { }
    }
    
    public abstract class MyItemBase<T> where T : MyItemBase<T>
    {
        protected MyCollection<T> _collection;
    
        protected MyItemBase(MyCollection<T> collection)
        {
            _collection = collection;
        }
    
        public void DoSomething()
        {
            _collection.Call(this);
        }
    }
    
    public class MyItem : MyItemBase<MyItem>
    {
        public MyItem(MyCollection<MyItem> Collection)
            : base(Collection)
        {
        }
    }
    

    【讨论】:

    • 将集合传递给 Item 似乎很奇怪,因为您可能将项目放在另一个列表中,然后反向引用现在无效。
    • 这就是我使用泛型的原因,以便反向引用遵循相同的合同。我正在使用 MVVM 模式,并且该集合有几个属性,这些属性被填充一次,然后被所有子视图模型使用。因此,将集合的引用传递给每个视图模型的构造函数似乎是正确的,这样它就可以访问更大的范围。也许我应该从集合中分离公共属性并将它们作为单独的引用传递给视图模型?
    • 我不知道你的设置,也许你设计这种方式是合理的,但这是我对它的价值的想法:将父列表传递给孩子,让孩子调用一个方法在作为this._collection.Call(this); 之类的参数传入的父级上,在大多数情况下都有改进的余地。它通常变成这样:而不是 this.parentcollection.call(this),它只是变成 base.call() 或只是 call(),其中基类 (MyItemBase) 执行列表的操作。
    • 免责声明:我只有您提出的问题可以使用,所以请谨慎对待我的建议,它可能对您不起作用。
    • Zasz,我很欣赏你的想法。我一直在反思您的 cmets,我认为我很有可能过度设计并错过了一种更简单的方法。应该可以将这两个类和适当的子类结合起来。谢谢!
    猜你喜欢
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2011-03-20
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多