Извлечение предметов из пользовательской коллекции - PullRequest
5 голосов
/ 21 марта 2011

У меня есть следующий класс

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

Мне нужно создать пользовательскую коллекцию, состоящую из объектов класса People, которая позволяет мне извлекать элементы по id и nameHash.Коллекция должна иметь возможность перебирать свои элементы, используя foreach:

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

Как мне это сделать?Если вы не можете дать подробный ответ, хотя бы дайте краткий план действий.Заранее спасибо!

Ответы [ 4 ]

3 голосов
/ 21 марта 2011

Есть ли конкретная причина, по которой это должна быть пользовательская коллекция? Почему не

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

вы можете извлекать элементы, используя id и nameHash, и вы можете перебирать PeopleCollection

2 голосов
/ 21 марта 2011

Если вы говорите о большой коллекции, и вам нужны более быстрые поиски на основе целого поля 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");
2 голосов
/ 21 марта 2011
class PeopleList : List<People> {

}

Вот и все. Просто наследуй от List<T> и все готово.

Кстати, вам следует пересмотреть свои соглашения об именах. «Люди» - это не хорошее имя для класса, представляющего одного человека. Вместо этого назовите его «Персона» и назовите свой список «Люди».

0 голосов
/ 21 марта 2011

У вас есть два варианта:

  1. Наследовать от существующего типа коллекции, как показано в других ответах.
  2. Реализация System.Collections.IEnumerable или *Интерфейс 1009 *System.Collections.Generic.IEnumerable<T>, что также означает написание собственной реализации System.Collections.IEnumerator или System.Collections.Generic.IEnumerator<T>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...