c# - 使用 IEnumerable<T> 创建通用集合的通用类

标签 c# oop generics

这是一个关于泛型的两 (2) 部分问题

我必须创建几个类似的类来模拟设计类似的数据库表。

所有表都包含一个 ID int 和一个 Text nvarchar(50) 字段。一两个可能包含一些其他字段。

我很少用 generics ,但我经常在这里看到它的例子。这是我最大的尝试创建一个泛型类用于另一个泛型类。

我的基本构造如下,我将通过注释指出不起作用的地方以及 Visual Studio 2010 显示的错误消息:

public class IdText {

  public IdText(int id, string text) {
    ID = id;
    Text = text;
  }

  public int ID { get; private set; }

  public string Text { get; private set; }

}

public class TCollection<T> : IEnumerable<T> where T : IdText {

  private List<T> list;

  public TCollection() {
    list = new List<T>();
  }

  public void Add(int id, string text) {
    foreach (var item in list) {
      if (item.ID == id) {
        return;
      }
    }
    list.Add(new T(id, text)); // STOP HERE
    // Cannot create an instance of the variable type 'T'
    // because it does not have the new() constraint
  }

  public T this[int index] {
    get {
      if ((-1 < 0) && (index < list.Count)) {
        return list[index];
      }
      return null;
    }
  }

  public T Pull(int id) {
    foreach (var item in list) {
      if (item.ID == id) {
        return item;
      }
    }
    return null;
  }

  public T Pull(string status) {
    foreach (var item in list) {
      if (item.Text == status) {
        return item;
      }
    }
    return null;
  }

  #region IEnumerable<T> Members

  public IEnumerator<T> GetEnumerator() {
    foreach (var item in list) yield return item;
  }

  #endregion

  #region IEnumerable Members

  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
    return list.GetEnumerator();
  }

  #endregion

}

Visual Studio 的 IntelliSence 要我添加 list.Add(T item),但我需要先创建它。

我试图将有问题的行 list.Add(new T(id, text)); 重写为 list.Add(new IdText(id, text)); ,但随后我收到消息 “无法从 IdText 转换为 T

我该如何解决这个问题?

下一步: 当我稍后实际创建此 IdText 类的一个版本时,我不确定如何在 TCollection 我为它设计的类。

例如,给定这个派生类:

public class ManufacturedPart : IdText {

  public ManufacturedPart(int id, string partNum, string description)
    : base(int id, string partNum) {
    Description = description;
  }

  public string Description { get; private set; }

}

...我是否还需要派生一个特殊版本的 TCollection 来配合它,就像这样?

public class ManufacturedParts<T> : IEnumerable<T> where T : ManufacturedPart {

  // OK, now I'm lost! Surely this can't be right!

}

最佳答案

1) 您可以使用 new() 约束,公开您的属性并添加无参数构造函数:

public class IdText
{
    public IdText()
    {
    }

    public IdText(int id, string text)
    {
        ID = id;
        Text = text;
    }

    public int ID { get; set; }

    public string Text { get; set; }

}

public class TCollection<T> : IEnumerable<T> where T : IdText, new()
{

    private List<T> list;

    public TCollection()
    {
        list = new List<T>();
    }

    public void Add(int id, string text)
    {
        foreach (var item in list)
        {
            if (item.ID == id)
            {
                return;
            }
        }
        list.Add(new T { ID = id, Text = text }); 
    }
}

2) 你有多种选择:

如果您希望您的集合存储任何 IdText(ManufacturedPart 或从 IdText 派生的任何其他内容):

TCollection<IdText> ss = new TCollection<IdText>();

目前,当您在 Add(int, string) 方法中实例化对象时,上面的代码只能存储 IdText,但是如果您提供 Add (T object) 方法,它可以存储任何 IdText 实例。

如果您希望您的集合仅包含 ManufacturedParts:

public class ManufacturedParts<T> : TCollection<T> where T : ManufacturedPart, new()
{
     // Provide here some specific implementation related to ManufacturedParts
     // if you want. For example, a TotalPrice property if ManufacturedPart
     // has a Price property.
}

TCollection<ManufacturedPart> ss2 = new ManufacturedParts<ManufacturedPart>();

或者更简单,如果你的集合没有根据存储对象的类型提供任何额外的方法:

TCollection<ManufacturedPart> ss2 = new TCollection<ManufacturedPart>();

更简单的是,如果您的目标只是存储对象,则不需要自定义集合:

List<IdText> ss2 = new List<IdText>();  // Uses the built-in generic List<T> type

关于c# - 使用 IEnumerable<T> 创建通用集合的通用类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9235511/

相关文章:

c# - Windows Phone 8 Web 浏览器任务

c# - 如何限制用户在类级别输入的数据类型

python - 基于文本的角色扮演游戏的早期阶段 - 类和方法

c++ - 使用类c++的登录系统

c# - IEqualityComparer 给出错误的结果

java - 创建一个泛型类,其类型参数仅限于某个父类(super class)

java - 将带有通配符泛型的集合转移到 Java 中的列表

c# - 如何在 C# 中将字符串转换为 cfstring

C# 通过预加载来优化函数

java - 创建一个包含大量静态字段的常量类是否可以?