Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ obj is MdFieldInfo fi &&
ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_tkField.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
HashCode.Combine(m_tkField, m_declaringType.GetUnderlyingNativeHandle(), m_reflectedTypeCache.GetRuntimeType().GetUnderlyingNativeHandle());
#endregion

#region FieldInfo Overrides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ obj is RtFieldInfo fi &&
ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_fieldHandle.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
HashCode.Combine(m_fieldHandle, m_reflectedTypeCache.GetRuntimeType().GetUnderlyingNativeHandle());

#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public override bool Equals(object? obj) =>
(MetadataUpdater.IsSupported && CacheEquals(obj));

public override int GetHashCode() =>
HashCode.Combine(m_handle.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
HashCode.Combine(m_handle, m_declaringType.GetUnderlyingNativeHandle());
#endregion

#region ICustomAttributeProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,10 @@ public override bool Equals(object? obj) =>
(MetadataUpdater.IsSupported &&
obj is RuntimeEventInfo ei &&
ei.m_token == m_token &&
ReferenceEquals(ei.m_declaringType, m_declaringType) &&
ReferenceEquals(ei.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
HashCode.Combine(m_token, m_reflectedTypeCache.GetRuntimeType().GetUnderlyingNativeHandle());
#endregion

#region ICustomAttributeProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,10 @@ public override string ToString()
// retrieve items from and insert items into s_methodInstantiations.

public override int GetHashCode() =>
HashCode.Combine(m_handle.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
HashCode.Combine(m_handle, m_reflectedTypeCache.GetRuntimeType().GetUnderlyingNativeHandle());

public override bool Equals(object? obj) =>
obj is RuntimeMethodInfo m && m_handle == m.m_handle &&
ReferenceEquals(m_declaringType, m.m_declaringType) &&
ReferenceEquals(m_reflectedTypeCache.GetRuntimeType(), m.m_reflectedTypeCache.GetRuntimeType());

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,10 @@ public override bool Equals(object? obj) =>
ReferenceEquals(this, obj) ||
(MetadataUpdater.IsSupported && obj is RuntimePropertyInfo rpi &&
rpi.m_token == m_token &&
ReferenceEquals(rpi.m_declaringType, m_declaringType) &&
ReferenceEquals(rpi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
HashCode.Combine(m_token, m_reflectedTypeCache.GetRuntimeType().GetUnderlyingNativeHandle());
#endregion

#region PropertyInfo Overrides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public sealed override bool Equals(object obj)

public sealed override int GetHashCode()
{
return _eventHandle.GetHashCode();
return HashCode.Combine(_eventHandle, ContextTypeInfo, ReflectedType);
}

public sealed override Type EventHandlerType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public sealed override bool Equals(object obj)

public sealed override int GetHashCode()
{
return _fieldHandle.GetHashCode();
return HashCode.Combine(_fieldHandle, _contextTypeInfo, _reflectedType);
}

public sealed override RuntimeFieldHandle FieldHandle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,17 @@ public sealed override bool Equals(object obj)

public sealed override int GetHashCode()
{
return _genericMethodDefinition.GetHashCode();
var hashcode = default(HashCode);

hashcode.Add(_genericMethodDefinition);
hashcode.Add(_genericTypeArguments.Length);

for (int i = 0; i < _genericTypeArguments.Length; i++)
{
hashcode.Add(_genericTypeArguments[i]);
}

return hashcode.ToHashCode();
}

internal sealed override int GenericParameterCount => _genericMethodDefinition.GenericParameterCount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public sealed override bool Equals(object obj)

public sealed override int GetHashCode()
{
return _common.GetHashCode();
return HashCode.Combine(_common, _reflectedType);
}

public sealed override RuntimeMethodHandle MethodHandle => GetRuntimeMethodHandle(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public sealed override MethodInfo GetGenericMethodDefinition()

public sealed override int GetHashCode()
{
return _declaringType.GetHashCode();
return HashCode.Combine(_syntheticMethodId, _declaringType);
}

public sealed override bool IsConstructedGenericMethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public sealed override bool Equals(object obj)

public sealed override int GetHashCode()
{
return _propertyHandle.GetHashCode();
return HashCode.Combine(_propertyHandle, ContextTypeInfo, _reflectedType);
}

public sealed override int MetadataToken
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,27 @@ public void EqualsTest(Type type1, string name1, Type type2, string name2, bool
}
}

[Fact]
public void GetHashCode_MultipleSubClasses_ShouldBeUnique()
{
var numberOfCollisions = 0;
var hashset = new HashSet<int>();

foreach (var type in new Type[] { typeof(BaseClass), typeof(SubClassA), typeof(SubClassB), typeof(SubClassC) })
{
foreach (var eventInfo in type.GetEvents())
{
if (!hashset.Add(eventInfo.GetHashCode()))
{
numberOfCollisions++;
}
}
}

// If intermittent failures are observed, it's acceptable to relax the assertion to allow some collisions.
Assert.Equal(0, numberOfCollisions);
}

[Theory]
[MemberData(nameof(Events_TestData))]
public void EventHandlerType(Type type, string name)
Expand Down Expand Up @@ -193,13 +214,19 @@ protected class BaseClass
public event EventHandler PublicEvent;
public static event EventHandler PublicStaticEvent;
public virtual event EventHandler PublicVirtualEvent;
public event EventHandler PublicEvent1;
public event EventHandler PublicEvent2;
public event EventHandler PublicEvent3;
}

protected class SubClass : BaseClass
{
public new event EventHandler PublicEvent;
public event EventHandler EventPublicNew;
}
protected class SubClassA : BaseClass { }
protected class SubClassB : BaseClass { }
protected class SubClassC : BaseClass { }
#pragma warning restore 0067
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,27 @@ public void GetHashCodeTest()
Assert.NotEqual(0, fieldInfo.GetHashCode());
}

[Fact]
public void GetHashCode_MultipleSubClasses_ShouldBeUnique()
{
var numberOfCollisions = 0;
var hashset = new HashSet<int>();

foreach (var type in new Type[] { typeof(FI_FieldArray), typeof(FI_FieldArraySubClassA), typeof(FI_FieldArraySubClassB), typeof(FI_FieldArraySubClassC) })
{
foreach (var fieldInfo in type.GetFields())
{
if (!hashset.Add(fieldInfo.GetHashCode()))
{
numberOfCollisions++;
}
}
}

// If intermittent failures are observed, it's acceptable to relax the assertion to allow some collisions.
Assert.Equal(0, numberOfCollisions);
}

[Theory]
[InlineData(typeof(FieldInfoTests), nameof(FieldInfoTests.intField), typeof(int))]
[InlineData(typeof(FieldInfoTests), nameof(FieldInfoTests.stringField), typeof(string))]
Expand Down Expand Up @@ -736,6 +757,9 @@ public class FI_FieldArray
public int[] intArray;
public object[] objectArray;
}
public class FI_FieldArraySubClassA : FI_FieldArray { }
public class FI_FieldArraySubClassB : FI_FieldArray { }
public class FI_FieldArraySubClassC : FI_FieldArray { }

public class FI_GenericClass<T> { public FI_GenericClass() { } }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,27 @@ public void GetHashCodeTest()
Assert.NotEqual(0, methodInfo.GetHashCode());
}

[Fact]
public void GetHashCode_MultipleSubClasses_ShouldBeUnique()
{
var numberOfCollisions = 0;
var hashset = new HashSet<int>();

foreach (var type in new Type[] { typeof(MI_BaseClass), typeof(MI_SubClassA), typeof(MI_SubClassB), typeof(MI_SubClassC) })
{
foreach (var methodInfo in type.GetMethods())
{
if (!hashset.Add(methodInfo.GetHashCode()))
{
numberOfCollisions++;
}
}
}

// If intermittent failures are observed, it's acceptable to relax the assertion to allow some collisions.
Assert.Equal(0, numberOfCollisions);
}

public static IEnumerable<object[]> Invoke_TestData()
{
yield return new object[] { typeof(MI_BaseClass), nameof(MI_BaseClass.VirtualReturnIntMethod), new MI_BaseClass(), null, 0 };
Expand Down Expand Up @@ -808,6 +829,10 @@ public void StringArrayMethod(string[] strArray) { }
public void MethodWithAttributes() { }
}

public class MI_SubClassA : MI_BaseClass { }
public class MI_SubClassB : MI_BaseClass { }
public class MI_SubClassC : MI_BaseClass { }

public class MethodInfoDummySubClass : MI_BaseClass
{
public override int VirtualReturnIntMethod() => 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,27 @@ public void GetHashCodeTest()
Assert.NotEqual(0, propertyInfo.GetHashCode());
}

[Fact]
public void GetHashCode_MultipleSubClasses_ShouldBeUnique()
{
var numberOfCollisions = 0;
var hashset = new HashSet<int>();

foreach (var type in new Type[] { typeof(BaseClass), typeof(SubClassA), typeof(SubClassB), typeof(SubClassC) })
{
foreach (var propertyInfo in type.GetProperties())
{
if (!hashset.Add(propertyInfo.GetHashCode()))
{
numberOfCollisions++;
}
}
}

// If intermittent failures are observed, it's acceptable to relax the assertion to allow some collisions.
Assert.Equal(0, numberOfCollisions);
}

[Theory]
[InlineData(typeof(BaseClass), "Item", new string[] { "Index" })]
[InlineData(typeof(BaseClass), nameof(BaseClass.ReadWriteProperty1), new string[0])]
Expand Down Expand Up @@ -484,6 +505,9 @@ public string Description
set { _description = value; }
}
}
public class SubClassA : BaseClass { }
public class SubClassB : BaseClass { }
public class SubClassC : BaseClass { }

public class CustomIndexerNameClass
{
Expand Down
Loading