假设我有这样的课程:
public class MyClass {
public int Id { get; set;}
public string Name { get; set; }
}
请注意,在我的例子中,这个类是失控的(来自第三方库)并且没有实现相等比较器。
现在我想要一个这些项目的集合,允许我根据它们的索引删除项目。
我希望能够做到:
void Foo()
{
var collection = new MyClassCollection();
var a = new MyClass { Id = 1, Name = "A" };
var b = new MyClass { Id = 2, Name = "B" };
collection.Add(a);
collection.Add(b);
// Other instance, that can come from external code
var otherA = new MyClass { Id = 1, Name = "A" };
var otherB = new MyClass { Id = 2, Name = "B" };
collection.Remove(otherA);
Console.WriteLine(collection.Count); // should output 1
Console.WriteLine(collection.Contains(otherB)); // should be true
collection.Add(otherB); //
Console.WriteLine(collection.Count); // should still output 1
}
实际上,在集合中搜索时只应考虑 ID。此代码是依赖序列化 DTO 的项目的一部分,因此不能依赖实例。
我应该如何实现 MyClassCollection?
我考虑了两种可能性,但对我来说都不优雅:
- 继承
List<MyClass>
并添加新方法。这将使 .Add 和 .Remove 保持原样,并可能导致消费者代码出现问题 - 创建一个实现
ICollection<MyClass>
. 创建一个内部Dictionary<int, MyClass>
来存储值,并使用字典内置功能在添加或删除之前检查键。通过包装内部字典值来实现接口的所有方法
我很感激你对我的案子的看法。
PS:我希望列表中的元素很少(<100 项)。性能不会是问题
编辑:我正在使用.Net 3.5 SP1。
Edit2:根据乔恩的建议,这是我的实现:
public class MyClassCollection : HashSet<MyClass>
{
private class MyClassIDComparer : IEqualityComparer<MyClass>{
public bool Equals(MyClass x, MyClass y)
{
if (x == null && y == null) return true;
else if (x == null || y == null) return false;
else return x.ID == y.ID;
}
public int GetHashCode(MyClass obj)
{
return obj.ID.GetHashCode();
}
}
public MyClassCollection() : base(new MyClassIDComparer())
{
}
}