C# 覆盖字典 ContainsKey
Posted
技术标签:
【中文标题】C# 覆盖字典 ContainsKey【英文标题】:C# override Dictionary ContainsKey 【发布时间】:2014-02-06 12:20:36 【问题描述】:我只是找不到任何合适的代码来做我需要的事情。
我正在使用Dict.ContainsKey
,但由于我总是创建我需要寻找的密钥,我总是为 ContainsKey 得到错误(因为 hashKey 不同,我创建的密钥我一直想检查)。
有人可以建议在这种情况下如何覆盖包含键或如何处理键比较?
我的字典看起来像
Dictionary<someObj, int>
public class someObj
public int someobjParam get;set;
public int someobjParamTwo get;set;
【问题讨论】:
【参考方案1】:您不需要覆盖ContainsKey
- 您需要或者覆盖someObj
中的Equals
和GetHashCode
(应重命名以符合.NET 命名约定,顺便说一句)或您需要将IEqualityComparer<someObj>
传递给Dictionary<,>
constructor。无论哪种方式,该代码都用于比较密钥(并从中获取哈希码)。
基本上,您需要让Equals
确定相等性,并使GetHashCode
为相等的对象返回相同的代码,理想情况下为不同的对象返回不同的代码 - 有关更多详细信息,请参阅Eric Lippert's article on GetHashCode
。
另外,您应该考虑使someObj
不可变:可变字典键通常是一个坏主意,就好像您在将它用作字典中的键后以哈希码敏感的方式修改键一样,您不会能够再次找到它。如果你的自定义类型真的是一个键,那么就让它不可变。
为简单起见,您还应该考虑让someObj
实现IEquatable<someObj>
,并考虑是否适合作为结构而不是类。如果您实现IEquatable<someObj>
,您应该也以一致的方式覆盖object.Equals
。通常object.Equals
实现只会调用最强类型的IEquatable<T>.Equals
实现。
【讨论】:
你能给我一个代码示例吗?我知道这是我在问题中提到的问题。 @OriRefael:嗯,我的哪一点回答会让你难过?您是否尝试过在someObj
中适当地覆盖Equals
和GetHashCode
?最好是自己尝试,而不是让其他人为您编写代码。另外,您的问题确实不清楚(在我看来),这无助于我们帮助您...
如果我现在没有压力并且需要快速解决问题,那你是对的。如果您只尝试提供帮助,那就太好了。不过谢谢你的解释。
@OriRefael:我正在试图提供帮助 - 我试图通过学习将建议付诸实践并为你提供建议来帮助你成为一名更好的开发人员关于其他要考虑的事情(不变性等)。
请别人写代码的可扩展性不是很好。另一种懒惰的方法(三种美德之一)是使用 Visual Studio 扩展来自动生成此代码。例如,R# 有一个函数“生成 -> 平等成员”来自动完成这些工作。【参考方案2】:
您不需要覆盖ContainsKey
,而是指示字典何时应该认为两个键相等。
一种方法是在您的密钥类中实现IEquatable<someObj>
。如果平等概念在您的应用中是全局性的,请执行此操作:
public class someObj : IEquatable<someObj>
public int someobjParam get;set;
public int someobjParamTwo get;set;
// override GetHashCode() and Equals(); for an example
// see http://msdn.microsoft.com/en-us/library/ms131190%28v=vs.110%29.aspx
另一种方法是实现 IEqualityComparer<someObj>
并将其传递给字典的构造函数。
【讨论】:
@Sameer:其实并没有什么不同,虽然我正在努力。 Jon 只是先按 Enter 键。 其实不一样。这个答案将相同的 java 语法与 C# 混合在一起,但它也以不同的方式解决了相同的问题(通过实现 ContainsKey 方法使用的接口)。编辑:现在 Jon Skeet 的回答也有 IEquatable 建议 @Jon:你使用了“implements”而不是“:”。 @JonSkeet:呵呵。谢谢。以上是关于C# 覆盖字典 ContainsKey的主要内容,如果未能解决你的问题,请参考以下文章