MethodInfo 可以安全地用于字典键吗?

Posted

技术标签:

【中文标题】MethodInfo 可以安全地用于字典键吗?【英文标题】:Can MethodInfo safely be used for dictionary keys? 【发布时间】:2021-06-19 03:01:20 【问题描述】:

我正在尝试使用 MethodInfo 实例作为字典键,但我无法验证 .net 运行时是否很好地支持这一点。

更准确地说,给定两个RuntimeMethodInfo 实例m1m2,它们是从 .net 反射 API 获得的并且表示相同的方法。 .net 运行时是否始终保证m1.GetHashCode() == m2.GetHashCode()m1.Equals(m2)

我可以在 *** 上找到同样的问题: Can MethodInfo be used as Dictionary key?

答案声称,是的,MethodInfo 可用于字典键。但是我无法验证此声明。

查看the source code of RuntimeMethodInfo,似乎GetHashCode() 的实现只是调用了RuntimeHelpers.GetHashCode() 的默认实现(当方法不是泛型时)。

如果我的理解是正确的RuntimeHelpers.GetHashCode(),只有在对象引用相同时才能保证返回相同的哈希码。

如果我的假设是正确的,这意味着 MethodInfo 不能安全地用作字典键,除非反射 API 始终保证为相同的给定方法返回相同的 MethodInfo 实例。是否有任何官方文件可以确认这一保证?

【问题讨论】:

您在寻找什么样的验证?在您的链接问题中发布已接受答案的用户是 Windows Master Ninja。如果你不相信他,你会接受什么? 你做过任何可以用来验证/反驳你论文的实验吗? 通过反射查询运行时的类型系统,它被大量缓存。是的,两个GetMethod() 调用将返回相同的实例。我不确定这是否记录在任何地方。 感谢您的回答!我确实注意到GetMethod 调用似乎产生了相同的MethodInfo 实例,但我找不到任何官方来源可以确认这是由运行时保证的。例如,我可以想象这是旨在减少内存分配的优化的副作用。然后我的代码可能会因一些极端情况而中断。 【参考方案1】:

我相信这里最好的选择是检查 C# 标准和文档。至于文档 - GetMethod 的返回值没有任何保证。因此,相同的调用是否会返回相同或不同的 MethodInfo 实例是特定于实现的。 MethodInfo.Equals 是否会考虑不同的实例,描述相同的方法是否真的相等?文档中也没有明确的保证,所以我更愿意考虑这也是特定于实现的。

简历:对于 POC/MVP,您可以使用 MethodInfo 作为键,因为当前实现确实需要将其用作键。但在任何长期/跨平台/等项目的情况下,我建议不要使用 MethodInfo 作为键,因为将来行为可能会改变,或者今天可能已经不同,但对于其他运行时。

【讨论】:

以上是关于MethodInfo 可以安全地用于字典键吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中,我可以使用元组作为字典中的键吗?

Python:可以将自定义类用作字典的键吗? [重复]

MethodInfo 用于 EntityCollection 而不是 Queryable

http://mydomain.com/me@mail.com 可以安全地用作 URL 吗?

获取嵌套字典值的安全方法

一个表可以有多个主键吗?