Ho un codice che confronta 2 PropertyInfos con Equals(). Anche se questo sembra normalmente al lavoro, ho incontrato una strana situazione in cui due riflessa informazioni della struttura oggetti per la stessa proprietà sottostante non sono uguali:Uguaglianza per .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 ???
Sembra PropertyInfo in realtà non implementare equals(), ma io pensavo che le cache di .NET riflettessero i membri in modo che la stessa istanza venisse sempre restituita. Certamente vedi a.GetType() == b.GetType() tutto il tempo. Non è questo il caso di PropertyInfos?
Alcune altre note: -Questo stranezza è accaduto durante l'esecuzione di un test di NUnit in .NET 4, VS2012, x86 build target -Questo non ha nemmeno accade per tutte le proprietà confrontiamo questo modo, ma non riesce costantemente su un proprietà.
Qualcuno può spiegare questo comportamento?
EDIT: nel caso in cui qualcuno è interessato, qui è la funzione EqualityComparison ho scritto per confrontare 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;
}
}
hai visto il codice decompilato? – pylover
@smartcaveman, hai intenzione di restituire false ogni volta che i tipi di dichiarazione sono uguali? Penso che ci dovrebbe essere un "non" lì dentro. Inoltre, le ultime righe del tuo metodo Equals sembrano essere troncate, poiché non ci sono dichiarazioni di ritorno o parentesi di chiusura. – Jax