A problem I often run into is needing to store a collection of objects in such a way that I can retrieve them by a particular field/property that is a unique "index" for that object. For example, I have a Person
object for which the name
field is a unique identifier, and I want to be able to retrieve from some collection of Person
objects the Person
whose name="Sax Russell"
. In Java I usually accomplish this by using a Map
where I actually want a Set
, and always using the "index" field of the object as its key in the map, i.e. peopleMap.add(myPerson.getName(), myPerson)
. I was thinking of doing the same thing in C# with Dictionary
s, like this:
class Person {
public string Name {get; set;}
public int Age {get; set;}
//...
}
Dictionary<string, Person> PersonProducerMethod() {
Dictionary<string, Person> people = new Dictionary<string, Person>();
//somehow produce Person instances...
people.add(myPerson.Name, myPerson);
//...
return people;
}
void PersonConsumerMethod(Dictionary<string, Person> people, List<string> names) {
foreach(var name in names) {
person = people[name];
//process person somehow...
}
}
However, this seems clumsy, and introduces a rather loose coupling between the keys of the Dictionary
and its values; I implicitly depend on every producer of Person
dictionaries using the Name
property as the key under which to store each Person
. I have no guarantee that the element at people["Sax Russell"]
is actually a Person
with Name="Sax Russell"
unless I double-check every time I access the dictionary.
Might there be some way to explicitly ensure that my collection of Person
objects is indexed by name, using custom equality comparers and/or LINQ queries? It's important that lookup stay constant-time, which is why I can't just use List.Find
or Enumerable.Where
. I've tried using a HashSet
and constructing it with an equality comparer that compares just the Name
field of the objects it's given, but there doesn't seem to be any way to then retrieve the Person
objects using just their name.