Artech's blog에서 확인한 다음 댓글에 대한 토론이있었습니다. 그 블로그는 중국어로만 작성되었으므로 여기서 간단히 설명하겠습니다. 코드 재현 :GetHashCode 및 같음은 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));
코드는 모든 FooAttribute
을 얻고 이름이 "C"인 하나를 제거합니다. 분명히 출력은 "A"와 "B"입니까? 모든 것이 순조롭게 진행된다면이 질문을 볼 수 없을 것입니다. 실제로 "AC" "BC"또는 이론적으로 올바른 "AB"를 얻을 것입니다 (제 컴퓨터에서 AC를 얻었고 블로그 작성자는 BC를 얻었습니다). 이 문제는 System.Attribute에서 GetHashCode/Equals를 구현할 때 발생합니다. 구현의 조각은 :
[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();
}
이 Type.GetFields
그래서 속성은 다음 Remove
무시됩니다 기본 클래스에서 FooAttribute
의 세 인스턴스 따라서 등가를 상속 (및 사용 방법은 임의로) 하나 걸립니다. 그래서 질문은 : 구현을위한 특별한 이유가 있습니까? 아니면 그냥 버그 야?
나는 그것이 문제가되는 실제 시나리오를 이미징하는 데 어려움이 있지만 버그라고 말하고 싶습니다. connect.microsoft.com에보고 해보십시오. – Joe
버그는 Equals()에 있습니다. GetHashCode()가 동일한 값을 반환해도 괜찮습니다. 동의하면 연결시 게시하십시오. 그게 큰 변화가 될 것이기 때문에 실제로 고칠 수 있을지는 의문입니다. –
@HansPassant : 정확합니다. 여기에 필자가 코드를 게시하고이 컴퓨터에 디스어셈블러가 없기 때문에'GetHashCode' 코드를 게시합니다. –