我认为这是我们经常遇到的问题。
class Person
{
public string place;
public string name;
public Person(string place, string name)
{
this.place = place;
this.name = name;
}
public bool Equals(Person other)
{
if (ReferenceEquals(null, other))
return false;
return name == other.name;
}
public override bool Equals(object obj)
{
return Equals(obj as Person);
}
public override int GetHashCode()
{
return name.GetHashCode();
}
public override string ToString()
{
return place + " - " + name;
}
}
说我有这门课。我可以实现KeyedCollection
这样的:
class Collection : KeyedCollection<string, Person>
{
protected override string GetKeyForItem(Person item)
{
return item.place;
}
}
这里的情况是默认Equals
值基于name
,Person
但在我的情况下,我正在创建一个自定义collection
,Person
每个place
. 换句话说place
将是独一无二的collection
。
Person p1 = new Person("Paris", "Paul");
Person p2 = new Person("Dubai", "Ali");
var collection = new Collection { p1, p2 };
var p3 = new Person("Paris", "Jean");
if (!collection.Contains(p3))
collection.Add(p3); // explosion
我明白这个问题。Contains(Person)
重载是进行基于值的Collection<T>.Contains(T)
线性搜索,同时Add(Person)
将值添加到内部字典中,这可能导致重复键异常。在这里,如果平等是基于place
,这个问题就不会存在。
我可以提供一个解决方法:
class Collection : KeyedCollection<string, Person>
{
protected override string GetKeyForItem(Person item)
{
return item.place;
}
new public bool Contains(Person item)
{
return this.Contains(GetKeyForItem(item));
}
}
但这又意味着如果我做一个将军
var p3 = new Person("Paris", "Jean");
bool b = collection.Contains(p3); //true
返回true
,但实际上Jean
还不存在collection
。所以我的问题是,只有KeyedCollection<K, T>
当Equals
仅基于? 我的问题在语义方面很少。我不是在寻求解决方案,但只是知道是否对何时有意义有一般的理解?我从文档中找不到与此主题相关的任何内容。K
T
KeyedCollection
更新:
我发现这里提到的确切问题http://bytes.com/topic/net/answers/633980-framework-bug-keyedcollection-t
提问者向 MS 提交了错误报告。引用他的话(2007 年 4 月 18 日):
我将此作为错误提交给 Microsoft,他们已经验证并接受了它。这是问题 ID 271542,可以在此处跟踪:
“我们已经在 WinXP pro SP2 和 VSTS2005 SP1 上重现了这个错误,我们正在将此错误发送给 Visual Studio 产品团队中的适当小组进行分类和解决。”
虽然我不认为这是一个错误,但这肯定是一个烦恼。但只是想知道 MS 一开始是如何接受这个错误的(预计现在找不到该页面)。Imo,它只是考虑不周的继承模型。