Artech's blogから見て、コメントに議論がありました。そのブログは中国語で書かれているので、私はここで簡単に説明します。再現するコード:GetHashCodeとEqualsは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();
}
これは基本クラスから継承されたプロパティがFooAttribute
(そしてRemove
の3つのインスタンスの等価性は、したがって、無視されるので、Type.GetFields
を使用します方法はをランダムにとする)。したがって、問題は、実装に特別な理由があるかどうかです。それとも単なるバグでしょうか?
私はそれが問題を引き起こす現実のシナリオをイメージングするのが難しいですが、それはバグだと思います。 connect.microsoft.comで報告することもできます。 – Joe
バグはEquals()にありますが、GetHashCode()が同じ値を返すことは大丈夫です。合意し、接続時にこれを投稿してください。それが突然の変化になるので、私は実際に彼らがそれを修正することを疑う。 –
@HansPassant:あなたは正しいです。ここで私は 'GetHashCode'のコードを投稿しています。なぜなら、著者がコードを投稿し、このPCに逆アセンブルされていないからです。 –