C#集合由属性索引?

前端之家收集整理的这篇文章主要介绍了C#集合由属性索引?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我经常遇到的一个问题是需要以这样的方式存储对象集合,以便我可以通过特定的字段/属性来检索它们,该字段/属性是该对象的唯一“索引”.例如,我有一个Person对象,其名称字段是唯一标识符,我希望能够从Person对象的一些集合中检索名称为“Sax Russell”的Person.在 Java中,我通常使用Map实现这一点,其中我实际上想要一个Set,并且总是使用对象的“index”字段作为其在地图中的键,即peopleMap.add(myPerson.getName(),myPerson).我想在C#中用Dictionarys做同样的事情,像这样:
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 : names) {
        person = people[name];
        //process person somehow...
    }
}

然而,这看起来很笨拙,并且在Dictionary的键和它的值之间引入了相当松散的耦合;我隐含地依赖于Person字典的每个生成器,使用Name属性作为存储每个Person的键.我不能保证人们[“Sax Russell”]的元素实际上是名字=“Sax Russell”的人,除非我每次访问字典时仔细检查.

有没有办法明确确保我的Person对象集合是通过名称索引,使用自定义相等比较器和/或LINQ查询?重要的是查找保持恒定时间,这就是为什么我不能只使用List.Find或Enumerable.Where.我已经尝试使用HashSet并使用相等比较器构建它,它只比较它给出的对象的Name字段,但似乎没有任何方法可以使用它们的名称来检索Person对象.

解决方法

您可以构建由字典支持的自己的集合来完成此任务.我们的想法是存储一个带有Person的委托,并通过读取Name属性返回一个字符串.

这是一个这样的集合的骨架解决方案:

public class PropertyMap<K,V> : ICollection<V> {
    private readonly IDictionary<K,V> dict = new Dictionary<K,V>();
    private readonly Func<V,K> key;
    public PropertyMap(Func<V,K> key) {
        this.key = key;
    }
    public void Add(V v) {
        dict.Add(key(v));
    }
    // Implement other methods of ICollection
    public this[K k] {
        get { return dict[k]; }
        set { dict[k] = value; }
    }
}

以下是如何使用它:

PropertyMap<string,Person> mp = new PropertyMap<string,Person>(
    p => p.Name
);
mp.Add(p1);
mp.Add(p2);

猜你在找的C#相关文章