Skip to content

Implement GetHashCode() via HashCode.Combine() #268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 1 addition & 10 deletions Extensions/Xtensive.Orm.Security/Permission.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,7 @@ public override bool Equals(object obj)
}

/// <inheritdoc/>
public override int GetHashCode()
{
unchecked {
int result = (Type != null ? Type.GetHashCode() : 0);
result = (result*397) ^ CanRead.GetHashCode();
result = (result*397) ^ CanWrite.GetHashCode();
result = (result*397) ^ (Query != null ? Query.GetHashCode() : 0);
return result;
}
}
public override int GetHashCode() => HashCode.Combine(Type, CanRead, CanWrite, Query);

#endregion

Expand Down
7 changes: 2 additions & 5 deletions Orm/Xtensive.Orm.Tests.Core/Caching/CachePerformanceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ public override bool Equals(object obj)
return Equals(obj as Item);
}

public override int GetHashCode()
{
return (Value!=null ? Value.GetHashCode() : 0);
}
public override int GetHashCode() => Value?.GetHashCode() ?? 0;

public override string ToString()
{
Expand Down Expand Up @@ -174,4 +171,4 @@ private void FetchTest(int count)
}
}
}
}
}
7 changes: 2 additions & 5 deletions Orm/Xtensive.Orm.Tests.Core/Caching/WeakestCacheTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ public override bool Equals(object obj)
return Equals(obj as Item);
}

public override int GetHashCode()
{
return (Value != null ? Value.GetHashCode() : 0);
}
public override int GetHashCode() => Value?.GetHashCode() ?? 0;

public override string ToString()
{
Expand Down Expand Up @@ -197,4 +194,4 @@ public void ProfileTest()
}
}
}
}
}
16 changes: 2 additions & 14 deletions Orm/Xtensive.Orm.Tests.Core/Modelling/IndexingModel/TypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,7 @@ public override bool Equals(object obj)
}

/// <inheritdoc/>
public override int GetHashCode()
{
unchecked {
int result = (Type!=null ? Type.GetHashCode() : 0);
result = (result * 397) ^ (IsNullable ? 1 : 0);
result = (result * 397) ^ Length;
result = (result * 397) ^ Scale;
result = (result * 397) ^ Precision;
if (Culture!=null)
result = (result * 397) ^ Culture.GetHashCode();
return result;
}
}
public override int GetHashCode() => HashCode.Combine(Type, IsNullable, Length, Scale, Precision, Culture);

/// <summary>
/// Implements the operator ==.
Expand Down Expand Up @@ -216,4 +204,4 @@ public TypeInfo(Type type, bool isNullable, int length, int scale, int precision
Precision = precision;
}
}
}
}
13 changes: 6 additions & 7 deletions Orm/Xtensive.Orm.Tests.Framework/Dynamic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,13 @@ internal class Signature : IEquatable<Signature>
public Signature(IEnumerable<DynamicProperty> properties)
{
this.properties = properties.ToArray();
hashCode = 0;
HashCode hc = new();
foreach (DynamicProperty p in properties)
{
hashCode ^= p.Name.GetHashCode() ^ p.Type.GetHashCode();
hc.Add(p.Name);
hc.Add(p.Type);
}
hashCode = hc.ToHashCode();
}

#region IEquatable<Signature> Members
Expand All @@ -241,10 +243,7 @@ public bool Equals(Signature other)

#endregion

public override int GetHashCode()
{
return hashCode;
}
public override int GetHashCode() => hashCode;

public override bool Equals(object obj)
{
Expand Down Expand Up @@ -2298,4 +2297,4 @@ internal static class Res
public const string CloseBracketOrCommaExpected = "']' or ',' expected";
public const string IdentifierExpected = "Identifier expected";
}
}
}
24 changes: 4 additions & 20 deletions Orm/Xtensive.Orm.Tests/Linq/LocalCollectionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ public override bool Equals(object obj)
return Equals((Poco<T>) obj);
}

public override int GetHashCode()
{
return Value.GetHashCode();
}
public override int GetHashCode() => Value.GetHashCode();
}

public class Poco<T1, T2>
Expand Down Expand Up @@ -85,12 +82,7 @@ public override bool Equals(object obj)
return Equals((Poco<T1, T2>) obj);
}

public override int GetHashCode()
{
unchecked {
return (Value1.GetHashCode() * 397) ^ Value2.GetHashCode();
}
}
public override int GetHashCode() => HashCode.Combine(Value1, Value2);

public Poco(T1 Value1, T2 Value2)
{
Expand Down Expand Up @@ -137,15 +129,7 @@ public override bool Equals(object obj)
return Equals((Poco<T1, T2, T3>) obj);
}

public override int GetHashCode()
{
unchecked {
int result = Value1.GetHashCode();
result = (result * 397) ^ Value2.GetHashCode();
result = (result * 397) ^ Value3.GetHashCode();
return result;
}
}
public override int GetHashCode() => HashCode.Combine(Value1, Value2, Value3);

public Poco()
{
Expand Down Expand Up @@ -942,4 +926,4 @@ private IEnumerable<Poco<int, decimal, string>> GetLocalItems(int count)
.ToList();
}
}
}
}
7 changes: 2 additions & 5 deletions Orm/Xtensive.Orm/Annotations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ public override bool Equals(object obj)
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A hash code for the current <see cref="LocalizationRequiredAttribute"/>.</returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
public override int GetHashCode() => base.GetHashCode();
}

/// <summary>
Expand Down Expand Up @@ -521,4 +518,4 @@ public PathReferenceAttribute([PathReference] string basePath)

[UsedImplicitly] public string BasePath { get; private set; }
}
}
}
5 changes: 1 addition & 4 deletions Orm/Xtensive.Orm/Arithmetic/ArithmeticRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ public override bool Equals(object obj) =>
obj is ArithmeticRules other && Equals(other);

/// <inheritdoc/>
public override int GetHashCode()
{
return ((byte)overflowBehavior << 8) | (byte)nullBehavior;
}
public override int GetHashCode() => ((byte) overflowBehavior << 8) | (byte) nullBehavior;


// Constructors
Expand Down
5 changes: 1 addition & 4 deletions Orm/Xtensive.Orm/Caching/WeakestCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,7 @@ public override bool Equals(object obj)
return Equals((WeakEntry) obj);
}

public override int GetHashCode()
{
return hashCode;
}
public override int GetHashCode() => hashCode;

#endregion

Expand Down
9 changes: 2 additions & 7 deletions Orm/Xtensive.Orm/Collections/FlagCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,7 @@ public override bool Equals(object obj)
}

/// <inheritdoc/>
public override int GetHashCode()
{
int result = keys.GetHashCode();
result = 29*result + flags.GetHashCode();
return result;
}
public override int GetHashCode() => HashCode.Combine(keys, flags);

#endregion

Expand Down Expand Up @@ -407,4 +402,4 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte

#endregion
}
}
}
12 changes: 2 additions & 10 deletions Orm/Xtensive.Orm/Collections/TypeRegistration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,7 @@ public override bool Equals(object obj)
}

/// <inheritdoc/>
public override int GetHashCode()
{
unchecked {
int result = (type!=null ? type.GetHashCode() : 0);
result = (result * 397) ^ (assembly!=null ? assembly.GetHashCode() : 0);
result = (result * 397) ^ (@namespace!=null ? @namespace.GetHashCode() : 0);
return result;
}
}
public override int GetHashCode() => HashCode.Combine(type, assembly, @namespace);

/// <inheritdoc/>
public static bool operator ==(TypeRegistration left, TypeRegistration right)
Expand Down Expand Up @@ -128,4 +120,4 @@ public TypeRegistration(Assembly assembly, string @namespace)
this.@namespace = @namespace;
}
}
}
}
10 changes: 2 additions & 8 deletions Orm/Xtensive.Orm/Comparison/ComparisonRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,7 @@ public override bool Equals(object obj) =>
obj is ComparisonRule other && Equals(other);

/// <inheritdoc/>
public override int GetHashCode()
{
int result = (int)Direction;
if (Culture != null)
result ^= Culture.GetHashCode();
return result;
}
public override int GetHashCode() => HashCode.Combine(Direction, Culture);

#endregion

Expand Down Expand Up @@ -200,4 +194,4 @@ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext contex
info.AddValue(nameof(Culture), cultureId);
}
}
}
}
22 changes: 12 additions & 10 deletions Orm/Xtensive.Orm/Comparison/ComparisonRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public sealed class ComparisonRules :
{
private readonly ComparisonRule value;
private readonly ComparisonRules[] composite;
private volatile int cachedHashCode;
private long cachedHashCode;

/// <summary>
/// Predefined rules with <see cref="Direction"/> = <see cref="Direction.None"/>.
Expand Down Expand Up @@ -199,18 +199,20 @@ public override bool Equals(object obj) =>
/// <inheritdoc/>
public override int GetHashCode()
{
if (cachedHashCode==0) lock (composite) if (cachedHashCode==0) {
var h = Volatile.Read(ref cachedHashCode);
if (h == 0) {
int tailIndex = TailIndex;
int result = value.GetHashCode();
if (tailIndex==0 && IsRecursive)
result ^= 29 * 22; // Hash affection by IsRecursive
HashCode hc = new();
hc.Add(value);
if (tailIndex == 0 && IsRecursive)
hc.Add(1); // Hash affection by IsRecursive
else
result ^= 29 * composite[tailIndex].GetHashCode();
hc.Add(composite[tailIndex]);
for (int i = 0; i < tailIndex; i++)
result ^= (composite[i].GetHashCode() << i);
cachedHashCode = result;
hc.Add(composite[i]);
Volatile.Write(ref cachedHashCode, (long)hc.ToHashCode() | (1L << 63)); // Set the highest bit as HasValue flag even when `hashCode == 0`
}
return cachedHashCode;
return (int) h;
}

#endregion
Expand Down Expand Up @@ -313,4 +315,4 @@ private ComparisonRules(ComparisonRule value, ComparisonRules[] composite, bool
this.composite = composite;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,11 @@ public bool Equals(T other)
}

/// <exception cref="NotSupportedException"><c>NotSupportedException</c>.</exception>
public override int GetHashCode()
{
public override int GetHashCode() =>
throw new NotSupportedException(string.Format(
Strings.ExTypeXMustImplementY,
typeof(T).GetShortName(),
typeof(IEquatable<T>).GetShortName()));
}


// Constructors
Expand All @@ -51,4 +49,4 @@ private NoSystemComparerHandler()
{
}
}
}
}
7 changes: 1 addition & 6 deletions Orm/Xtensive.Orm/Conversion/Biconverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,7 @@ public override bool Equals(object obj) =>
obj is Biconverter<TFrom, TTo> other && Equals(other);

/// <inheritdoc/>
public override int GetHashCode()
{
unchecked {
return ((ConvertForward!=null ? ConvertForward.GetHashCode() : 0) * 397) ^ (ConvertBackward!=null ? ConvertBackward.GetHashCode() : 0);
}
}
public override int GetHashCode() => HashCode.Combine(ConvertForward, ConvertBackward);

#endregion

Expand Down
11 changes: 2 additions & 9 deletions Orm/Xtensive.Orm/Core/HasVersion{TValue,TVersion}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,7 @@ public override bool Equals(object obj) =>
obj is HasVersion<TValue, TVersion> other && Equals(other);

/// <inheritdoc/>
public override int GetHashCode()
{
unchecked {
return
((Value!=null ? Value.GetHashCode() : 0) * 397) ^
(Version!=null ? Version.GetHashCode() : 0);
}
}
public override int GetHashCode() => HashCode.Combine(Value, Version);

/// <summary>
/// Checks specified objects for equality.
Expand Down Expand Up @@ -114,4 +107,4 @@ public HasVersion(TValue value, TVersion version)
Version = version;
}
}
}
}
7 changes: 1 addition & 6 deletions Orm/Xtensive.Orm/Core/Pair{TFirst,TSecond}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,7 @@ public override bool Equals(object obj) =>
obj is Pair<TFirst, TSecond> other && Equals(other);

/// <inheritdoc/>
public override int GetHashCode()
{
unchecked {
return ((First?.GetHashCode() ?? 0) * 397) ^ (Second?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(First, Second);

/// <summary>
/// Checks specified objects for equality.
Expand Down
Loading