Viendo de Artech's blog y luego tuvimos una discusión en los comentarios. Dado que ese blog está escrito solo en chino, estoy tomando una breve explicación aquí. El código para reproducir:GetHashCode e Iguales se implementan incorrectamente en System.Attribute?
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public abstract class BaseAttribute : Attribute
{
public string Name { get; set; }
}
public class FooAttribute : BaseAttribute { }
[Foo(Name = "A")]
[Foo(Name = "B")]
[Foo(Name = "C")]
public class Bar { }
//Main method
var attributes = typeof(Bar).GetCustomAttributes(true).OfType<FooAttribute>().ToList<FooAttribute>();
var getC = attributes.First(item => item.Name == "C");
attributes.Remove(getC);
attributes.ForEach(a => Console.WriteLine(a.Name));
El código recibe toda FooAttribute
y elimina la persona cuyo nombre es "C". Obviamente, la salida es "A" y "B"? Si todo marchara bien, no verías esta pregunta. De hecho, obtendrás "AC" "BC" o incluso corregirás "AB" teóricamente (obtuve AC en mi máquina, y el autor del blog obtuvo BC). El problema es el resultado de la implementación de GetHashCode/Equals en System.Attribute. Un fragmento de la aplicación:
[SecuritySafeCritical]
public override int GetHashCode()
{
Type type = base.GetType();
//*****NOTICE***** FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
object obj2 = null;
for (int i = 0; i < fields.Length; i++)
{
object obj3 = ((RtFieldInfo) fields[i]).InternalGetValue(this, false, false);
if ((obj3 != null) && !obj3.GetType().IsArray)
{
obj2 = obj3;
}
if (obj2 != null)
{
break;
}
}
if (obj2 != null)
{
return obj2.GetHashCode();
}
return type.GetHashCode();
}
Utiliza Type.GetFields
lo que las propiedades heredadas de clase base son ignorados, por lo tanto, la equivalencia de los tres casos de FooAttribute
(y entonces la Remove
método toma uno aleatoriamente). Entonces la pregunta es: ¿hay alguna razón especial para la implementación? ¿O solo es un error?
Yo diría que es un error, aunque tengo dificultades para imaginar un escenario del mundo real donde podría causar un problema. Podría considerar informarlo en connect.microsoft.com. – Joe
El error está en Equals(), está bien que GetHashCode() devuelva valores idénticos. De acuerdo, publica esto en connect. Realmente dudo que lo arreglen porque sería un cambio radical. –
@HansPassant: Tiene razón. Aquí publico el código de 'GetHashCode' solo porque el autor publicó el código y no tengo desensamblador en esta pc. –