当字体用作键时,.NET Hashtable 是否使用专用的字体相等比较器?

Does .NET Hashtable uses the specialized Font equality comparer when fonts are used as keys?

提问人:TecMan 提问时间:7/20/2023 更新时间:7/20/2023 访问量:43

问:

我需要创建一组唯一的 Font 对象,每个对象都应该有一个关联的对象。这应该在 .NET Framework WinForms 应用中完成。这些 Font 对象来自不同的源,如果不同的 Font 对象具有相同的名称、大小和其他特征,则它们实际上可能是相同的。似乎 Hashtable 类可用于此目的。下面是适用于 .NET Framework 的全新 WinForms 应用中的简单测试:

private void Form1_Load(object sender, EventArgs e)
{
    Font font1 = new Font(this.Font, FontStyle.Regular);
    Font font2 = new Font("Microsoft Sans Serif", 8.25f);
    Hashtable ht = new Hashtable();
    ht.Add(font1, 1);
    ht.Add(font2, 2);
}

添加 font2 的最后一个语句引发以下异常:

System.ArgumentException HResult=0x80070057 Message=Item 具有 已添加。字典中的键:'[字体:名称=Microsoft Sans 衬线,大小=8.25,单位=3,GdiCharSet=1,GdiVerticalFont=False]' 键 添加:'[字体:名称=Microsoft Sans Serif,大小=8.25,单位=3, GdiCharSet=1, GdiVerticalFont=False]' Source=mscorlib 堆栈跟踪: 在 System.Collections.Hashtable.Insert (对象键、对象 nvalue、 布尔值加法)在 System.Collections.Hashtable.Add(对象键,对象) 值) 在 Font_Hashtable.Form1.Form1_Load (对象发送方,EventArgs e)

这证明专用的 Font 相等比较器用于检查 Font 对象是否用作 Hashtable 键。我想知道 - 我们真的可以在这种情况下使用哈希表吗?据我所知,如果键是对象,.NET Hashtables 应该通过引用比较键,如果是这种情况,上面的代码中应该没有例外。

C# 字体 哈希表 相等 IECqualityComparer

评论

1赞 Selvin 7/20/2023
据我所知,.NET Hashtables 应该通过引用比较键,如果它们是对象,不,它们不是(好吧,不仅)......他们依赖和......因此,某些字体是“相同”的这一事实在于 Font 对这些方法的实现GetHashCodeEquals
0赞 Ralf 7/20/2023
source.dot.net/#System.Drawing.Common/System/Drawing/......
0赞 Selvin 7/20/2023
...拉尔夫提供
0赞 Tim Schmelter 7/20/2023
为什么你仍然使用古代而不是 ?HashtableDictionary<TKey, TValue>
1赞 Tim Schmelter 7/20/2023
@TecMan:是的,差不多。字典将检查是否存在具有相同哈希码的项目,如果有,则两者是否相等。

答:

1赞 Tim Schmelter 7/20/2023 #1

“添加”中检查是否已包含该键,则将引发此异常。因此,它会检查是否存在具有相同哈希码的哈希码。如果是这样,它会检查它们是否相等,首先检查它是否是相同的引用(对象。ReferenceEquals)。如果不是,它会检查它们是否相等。通过构造函数中给定的 KeyComaprer 或 .如果被覆盖,则 Font 将覆盖 Equals,则使用该 Equals。Hashtableobject.EqualsEquals

文档还提到了它:

“默认的哈希代码提供程序是每个键的实现 GetHashCode() 和默认比较器是每个键的实现 等于(对象)。

由于首先使用,因此始终覆盖并一起使用。两个相等的对象必须具有相同的哈希码(但相同的哈希码并不一定意味着相等)。GetHashCodeEqualsGetHashCode


顺便说一句,没有理由再使用旧的了。在这里,您应该使用 .HashtableDictionary<Font, float>

如果您使用 a 或 generic 对此问题没有影响:如果有另一个具有相同哈希码的项目,两者都在检查添加,如果是这样,如果两个项目相等,那么你会得到这个。HashTableDictionary<TKey, TValue>ArgumentException

两者都使用传递的自定义(构造函数)或(如果不是重写对象。等于,只是比较引用)。IEqalityComparerEquals