【问题标题】:C# generics, design idea, maybeC#泛型,设计理念,也许
【发布时间】:2012-02-15 12:12:30
【问题描述】:

我是 C# 的新手,我正在研究它的可能性。

现在我有点困惑,我想使用泛型...列出泛型类型。我想在单个父类中创建一个基本的列表功能,并命名我的子类应该包含的类类型。

说,我创建了一个类

class ItemList<T> : IList<T> {}

并实现 IList 接口。 T 在 ItemList 中定义为

public T this[int index] { get; set; }

然后,我想拥有一个或多个 ItemList 的子类。例如

class ProductList : ItemList<ProductItem> {}

class CategoryList : ItemList<CategoryItem> {}

现在,当我在 ItemList 中实现 IList 接口时,我希望能够使用标识符 this 或 ProductList 实例访问 IndexOf、Add、Insert 等方法

ProductItem product = new ProductItem();
ProductList products = new ProductList();
products.Add(product);

3rd line products.Add is error.

ProductList' 不包含“添加”的定义,并且 没有扩展方法“添加”接受类型的第一个参数 可以找到 ProductList(您是否缺少使用 指令还是程序集引用?

我是否遗漏了一些语法部分或者这个概念是不可能的?这个想法(现在)只是为了简化以后的使用——如果我有一个 ProductList 类,它会包含 ProductItem 是合乎逻辑的,我为什么要像

一样使用它
ProductList<ProductItem> products = new ProductList<ProductItem>(); 

希望你明白我的意思。

编辑 - 只是为了清楚这里的对象层次结构...... 类 ItemList 使用方法存根实现 IList 接口 类 ProductList 继承 ItemList 类 方法存根抛出错误,但它发生在运行时。

ItemList 的详细信息

class ItemList<T> : IList<T>
    {

        public T this[int index] { get; set; }
        private List<T> fList = new List<T>();

        int IList<T>.IndexOf(T item)
        {
            return fList.IndexOf(item);
        }

        void ICollection<T>.Add(T item)
        {
            fList.Add(item);
        }

        void IList<T>.Insert(int index, T item)
        {
            fList.Insert(index, item);
        }
        void IList<T>.RemoveAt(int index)
        {
            throw new NotImplementedException();
        }
....
}

【问题讨论】:

  • 乍一看还不错,那么错误是什么意思 - 编译/运行时?
  • 您实现IList&lt;T&gt; 是因为您想了解泛型集合的工作原理,还是有其他原因避免直接从List&lt;T&gt; 继承此功能?
  • 不知道是不是NotImplementedException?
  • 很抱歉,我以为人们会把它放在他们的小指头上,现在一切对我来说都是基础。它是一个编译时错误。我会更新问题。
  • ItemList如何实现Add?向我们展示代码。我猜你正在使用显式实现,它不会在没有类型转换的情况下使 Add 可见。

标签: c# list generics


【解决方案1】:

哦,这很明显。你实现了接口explicitly .您可以在调用方法之前将产品转换为 ICollection

(products as ICollection<ProductItem>).Add(product);

或者,更好的是,您可以隐式实现 Add 方法,如下所示:

public void Add(T item) {
    fList.Add(item);
}

【讨论】:

  • 我想我不知道显式/隐式差异。我会将您的答案标记为正确,因为它确实“一针见血”。
【解决方案2】:

由于您正在实现一个接口,因此您需要使用自己的代码来实现这些方法。

或者,您可以从 List 而不是 IList 继承。

【讨论】:

  • 看来已经完成了。毕竟错误不在类的声明中……
  • 有点迂腐:我不会说从接口“继承”,而是“实现”接口。否则,这是正确的。
  • 嗯,ItemList 正在实现接口 IList,大多数方法都有方法存根,我只更改了 Add 和 IndexOf。 ItemList 是一个类而不是一个接口,所以 ProductList 是在继承一个类......还是不是?
  • 我在考虑继承 List,但作为第二种选择。如果可以通过这种方式实现 IList,以后应该会给我一些其他的灵活性。
  • @Sofija - 一般来说,从 List&lt;T&gt; 继承是所有 99% 的情况都需要(或其相关集合之一)。我并不是说没有小众的情况可以提供额外的灵活性,但如果有必要,以后可以很容易地改变它。
【解决方案3】:

This answer 一针见血。当显式实现接口方法时,您不会在基于类类型键入的变量上看到它们。您必须将它们强制转换为包含该方法的接口。

您可能已经注意到,在IList&lt;T&gt; 接口上实现所有方法需要花费大量工作。你确定这是你想做的吗?扩展 List&lt;T&gt; 类会简单得多。或者,更好的是,为什么不将列表作为单独的属性公开?

public class ItemList<T>
{
    private List<T> _itemList = new List<T>();
    public IList<T> Items {get {return _itemList;}}
    // add other features here.
}

当然,这是假设您有一些其他功能要添加到ItemList。完全跳过ItemList&lt;T&gt; 类实际上可能更有意义:

public class ProductList : List<ProductItem> {}

简而言之,您尝试完成的模式通常最好避免。如果您分享您认为有必要的原因,我们可能会向您展示其他方法来以更少的工作完成相同的结果。

【讨论】:

  • 我根本不相信这种模式是必要的,我只是在测试看看可能性,就像我说的那样,使用接口而不是扩展类的想法在以后更灵活。您可以保留相同的标准方法来操作集合,但可以以任何您喜欢的方式更改实现,IList 与 gridviews 一起使用。我认为这对这个问题并不重要......最后我可能不会在这里使用这个组织,我可能会在其他地方使用它..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多