从自定义集合中检索项目

时间:2011-03-21 18:59:53

标签: c# collections

我有以下课程

public class People
{
    public int id;
    public string nameHash;
    public string name;
}

我需要创建一个自定义集合,它由类People的对象组成,可以让我按idnameHash检索元素。该集合必须能够使用foreach迭代其元素:

foreach (People person in PeopleCollection) { ... }

我该怎么做?如果你不能给出详细的答案,至少要给出一个简短的行动计划。提前谢谢!

4 个答案:

答案 0 :(得分:3)

为什么它必须是自定义集合有特定原因吗? 为什么不

List<People> PeopleCollection = new List<People>();

您可以使用idnameHash检索元素,并且可以迭代PeopleCollection

答案 1 :(得分:2)

class PeopleList : List<People> {

}

这就是它。只需继承List<T>即可。

顺便说一句,你应该重新考虑你的命名惯例。对于代表一个人的班级来说,“人”并不是一个好名字。将其命名为“人”,并将列表命名为“人员”。

答案 2 :(得分:2)

如果您正在讨论大型集合,并且希望基于整数Id或字符串NameHash字段进行更快的查找,同时仍支持foreach (Foo f in fooCollection)模式,那么您可以滚动你自己的收藏包装了一对词典。原油实施,未经过全面测试:

class Person
{
    public int Id { get; private set; }
    public string NameHash { get; private set; }
    public string Name { get; private set; }

    public Person(int id, string nameHash, string name)
    {
        Id = id;
        NameHash = nameHash;
        Name = name;
    }
}

class People : IEnumerable<Person>
{
    private Dictionary<int, Person> personDictionary = new Dictionary<int, Person>();
    private Dictionary<string, int> hashIdMap = new Dictionary<string, int>();

    public void Add(Person person)
    {
        if (person == null)
            throw new ArgumentNullException("person");

        if (personDictionary.ContainsKey(person.Id))
            throw new InvalidOperationException("person Id is already referenced in collection.");

        if (hashIdMap.ContainsKey(person.NameHash))
            throw new InvalidOperationException("person NameHash is already referenced in collection.");

        personDictionary.Add(person.Id, person);
        hashIdMap.Add(person.NameHash, person.Id);
    }

    public Person this[int id]
    {
        get
        {
            if (!personDictionary.ContainsKey(id))
                throw new ArgumentOutOfRangeException("Id is not in the collection.");

            return personDictionary[id];
        }
    }

    public Person this[string nameHash]
    {
        get
        {
            if (!hashIdMap.ContainsKey(nameHash))
                throw new ArgumentOutOfRangeException("NameHash is not in the collection.");

            return this[hashIdMap[nameHash]];
        }
    }

    public IEnumerator<Person> GetEnumerator()
    {
        foreach (KeyValuePair<int, Person> pair in personDictionary)
            yield return pair.Value;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

...

static void Main()
{
    Person personA = new Person(1, "A", "Apple");
    Person personB = new Person(2, "B", "Banana");
    Person personC = new Person(3, "C", "Cherry");

    People people = new People();
    people.Add(personA);
    people.Add(personB);
    people.Add(personC);

    Person foo = people[1];
    Person bar = people["C"];

    Debug.Assert(foo.Name == "Apple");
    Debug.Assert(bar.Name == "Cherry");

    foreach (Person person in people)
        Debug.WriteLine(person.Name);
}

当然,如果您正在处理一个小型集合,您可以简单地使用List<T>并使用LINQ或已定义的Find方法。如

Person personA = collection.FirstOrDefault(p => p.Id == 42);
Person personB = collection.Find(p => p.NameHash == "Blah");

答案 3 :(得分:0)

你有两个选择:

  1. 继承现有的集合类型,如其他答案所示。
  2. 实施System.Collections.IEnumerableSystem.Collections.Generic.IEnumerable<T>界面,这也意味着编写自己的System.Collections.IEnumeratorSystem.Collections.Generic.IEnumerator<T>实施