Tôi có một số mã so sánh 2 PropertyInfos với Equals(). Trong khi điều này thường dường như làm việc, tôi đã chạy vào một tình huống kỳ lạ nơi hai phản ánh thông tin thuộc tính đối tượng cho các tài sản cơ bản giống nhau không bằng nhau:Sự bình đẳng cho .NET PropertyInfos
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 ???
Dường như PropertyInfo không thực sự thực hiện Equals(), nhưng tôi nghĩ rằng bộ đệm .NET phản ánh các thành viên sao cho cùng một cá thể luôn được trả về. Bạn chắc chắn thấy a.GetType() == b.GetType() mọi lúc. Đây có phải là trường hợp của PropertyInfos không?
Một số lưu ý khác: -Đây weirdness xảy ra khi chạy một kiểm tra NUnit trong .NET 4, VS2012, x86 xây dựng mục tiêu -Đây thậm chí không xảy ra cho tất cả các thuộc tính chúng ta so sánh cách này, nhưng nó không thành công liên tục trên một bất động sản.
Có ai có thể giải thích hành vi này không?
EDIT: trong trường hợp có ai quan tâm, đây là chức năng EqualityComparison tôi đã viết để so sánh MemberInfos:
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;
}
}
bạn đã thấy mã được biên dịch chưa? – pylover
@smartcaveman, bạn có ý định trả về false bất cứ khi nào các loại khai báo bằng nhau không? Tôi nghĩ rằng nên có một "không" trong đó. Ngoài ra, vài dòng cuối cùng của phương thức Equals của bạn dường như bị cắt bỏ, vì không có câu lệnh trả về hoặc dấu ngoặc đóng. – Jax