gpt4 book ai didi

c# - .NET PropertyInfos 的平等

转载 作者:太空狗 更新时间:2023-10-29 19:56:03 25 4
gpt4 key购买 nike

我有一些代码将 2 PropertyInfos 与 Equals() 进行比较。虽然这通常看起来可行,但我遇到了一个奇怪的情况,即同一基础属性的两个反射属性信息对象不相等:

PropertyInfo prop1, prop2; // both are public and not static
Console.WriteLine(prop1 == prop2); // false ???
Console.WriteLine(Equals(prop1, prop2)); // false ???
Console.WriteLine(prop1.DeclaringType == prop2.DeclaringType); // true
Console.WriteLine(prop1.ReturnType == prop2.ReturnType); // true
Console.WriteLine(prop1.Name == prop2.Name); // true
Console.WriteLine(prop1.DeclaringType.GetProperties().Contains(prop1)); // true
Console.WriteLine(prop2.DeclaringType.GetProperties().Contains(prop2)); // false ???

看起来 PropertyInfo 并没有实际实现 Equals(),但我认为 .NET 缓存反射成员以便始终返回相同的实例。您肯定会一直看到 a.GetType() == b.GetType() 。 PropertyInfo 不是这样吗?

一些其他注意事项:- 在 .NET 4、VS2012、x86 构建目标中运行 NUnit 测试时发生了这种怪事- 这甚至不会发生在我们以这种方式比较的所有属性上,但它在一个属性上始终失败。

谁能解释这种行为?

编辑:如果有人感兴趣,这里是我编写的用于比较 MemberInfos 的 EqualityComparison 函数:

public class MemberEqualityComparer : EqualityComparer<MemberInfo> {
public override bool Equals(MemberInfo @this, MemberInfo that) {
if (@this == that) { return true; }
if (@this == null || that == null) { return false; }

// handles everything except for generics
if (@this.MetadataToken != that.MetadataToken
|| !Equals(@this.Module, that.Module)
|| this.Equals(@this.DeclaringType, that.DeclaringType))
{
return false;
}

bool areEqual;
switch (@this.MemberType)
{
// constructors and methods can be generic independent of their types,
// so they are equal if they're generic arguments are equal
case MemberTypes.Constructor:
case MemberTypes.Method:
var thisMethod = @this as MethodBase;
var thatMethod = that as MethodBase;
areEqual = thisMethod.GetGenericArguments().SequenceEqual(thatMethod.GetGenericArguments(),
this);
break;
// properties, events, and fields cannot be generic independent of their types,
// so if we've reached this point without bailing out we just return true.
case MemberTypes.Property:
case MemberTypes.Event:
case MemberTypes.Field:
areEqual = true;
break;
// the system guarantees reference equality for types, so if we've reached this point
// without returning true the two are not equal
case MemberTypes.TypeInfo:
case MemberTypes.NestedType:
areEqual = false;
break;
default:
throw new NotImplementedException(@this.MemberType.ToString());
}

public override int GetHashCode(MemberInfo memberInfo) {
if (memberInfo == null) { return 0; }

var hash = @this.MetadataToken
^ @this.Module.GetHashCode()
^ this.GetHashCode(@this.DeclaringType);
return hash;
}
}

最佳答案

对象标识只被 promise 用于 Type 类,而不是用于其他反射类。比较相等性的一种可能合理方法是检查属性是否具有相同的元数据标记并且来自相同的模块。所以试试这个:

bool equal = prop1.MetadataToken == prop2.MetadataToken &&
prop1.Module.Equals(prop2.Module);

只要适用 ecma 335,这就有意义。我无法根据您的代码对此进行测试,因为您没有发布它。所以试试吧。

关于c# - .NET PropertyInfos 的平等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13615927/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com