Skip to content

Commit

Permalink
Implement missing GetHashCode() on several classes/structs (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
josesimoes authored Aug 2, 2018
1 parent 7844fce commit 1b6a37c
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 35 deletions.
7 changes: 6 additions & 1 deletion source/System/ComponentModel/EditorBrowsableAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public enum EditorBrowsableState
/// <summary>
/// Specifies that a property or method is viewable in an editor. This class cannot be inherited.
/// </summary>
[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate)]
public sealed class EditorBrowsableAttribute : Attribute
{
private readonly EditorBrowsableState _browsableState;
Expand Down Expand Up @@ -75,5 +75,10 @@ public EditorBrowsableState State
}
}

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode() => base.GetHashCode();
}
}
10 changes: 10 additions & 0 deletions source/System/DateTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -652,5 +652,15 @@ public String ToString(String format)
{
return Compare(t1, t2) >= 0;
}

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
ulong internalTicks = _ticks;
return (((int)internalTicks) ^ ((int)(internalTicks >> 0x20)));
}
}
}
8 changes: 8 additions & 0 deletions source/System/Delegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,13 @@ public extern Object Target
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern bool operator !=(Delegate d1, Delegate d2);

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return GetType().GetHashCode();
}
}
}
18 changes: 18 additions & 0 deletions source/System/MulticastDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,23 @@ public abstract class MulticastDelegate : Delegate
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern bool operator !=(MulticastDelegate d1, MulticastDelegate d2);

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override sealed int GetHashCode()
{
return base.GetHashCode();
}

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="obj">A 32-bit signed integer hash code.</param>
/// <returns></returns>
public override bool Equals(object obj)
{
return base.Equals(obj);
}
}
}
34 changes: 34 additions & 0 deletions source/System/String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -773,5 +773,39 @@ public String PadRight(int totalWidth, char paddingChar = ' ')
}
}

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{

unsafe
{
fixed (char* src = this)
{
int hash1 = (5381<<16) + 5381;
int hash2 = hash1;

// 32 bit machines.
int* pint = (int *)src;
int len = this.Length;
while (len > 2)
{
hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ pint[1];
pint += 2;
len -= 4;
}

if (len > 0)
{
hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
}

return hash1 + (hash2 * 1566083941);
}
}
}
}
}
8 changes: 8 additions & 0 deletions source/System/TimeSpan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,5 +345,13 @@ public double TotalMilliseconds
/// <returns>true if the value of t1 is greater than or equal to the value of t2; otherwise, false.</returns>
public static bool operator >=(TimeSpan t1, TimeSpan t2) => t1._ticks >= t2._ticks;

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return (int)_ticks ^ (int)(_ticks >> 32);
}
}
}
4 changes: 3 additions & 1 deletion source/System/ValueType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ namespace System
/// Provides the base class for value types.
/// </summary>
[Serializable]
#pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
// It would require to implement this on a call to native which seems a waste of resources.
public abstract class ValueType
#pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode()
{

/// <summary>
Expand All @@ -22,6 +25,5 @@ public abstract class ValueType
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
[MethodImpl(MethodImplOptions.InternalCall)]
public override extern bool Equals(Object obj);

}
}
73 changes: 40 additions & 33 deletions source/System/Version.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ namespace System
public sealed class Version // : ICloneable, IComparable, IComparable<Version>, IEquatable<Version>
{
// AssemblyName depends on the order staying the same
private readonly int _major;
private readonly int _minor;
private readonly int _build;// = -1;
private readonly int _revision;// = -1;
private readonly int _Major;
private readonly int _Minor;
private readonly int _Build = -1;
private readonly int _Revision = -1;

/// <summary>
/// Initializes a new instance of the Version class with the specified major, minor, build, and revision numbers.
Expand All @@ -29,10 +29,10 @@ public Version(int major, int minor, int build, int revision)
{
if (major < 0 || minor < 0 || revision < 0 || build < 0) throw new ArgumentOutOfRangeException();

_major = major;
_minor = minor;
_revision = revision;
_build = build;
_Major = major;
_Minor = minor;
_Revision = revision;
_Build = build;
}

/// <summary>
Expand All @@ -46,49 +46,37 @@ public Version(int major, int minor)
if (major < 0) throw new ArgumentOutOfRangeException();
if (minor < 0) throw new ArgumentOutOfRangeException();

_major = major;
_minor = minor;
_Major = major;
_Minor = minor;

// Other 2 initialize to -1 as it done on desktop and CE
_build = -1;
_revision = -1;
_Build = -1;
_Revision = -1;
}

/// <summary>
/// Gets the value of the major component of the version number for the current Version object.
/// </summary>
/// <value>The major version number.</value>
public int Major
{
get { return _major; }
}
public int Major => _Major;

/// <summary>
/// Gets the value of the minor component of the version number for the current Version object.
/// </summary>
/// <value>The minor version number.</value>
public int Minor
{
get { return _minor; }
}
public int Minor => _Minor;

/// <summary>
/// Gets the value of the revision component of the version number for the current Version object.
/// </summary>
/// <value>The revision version number.</value>
public int Revision
{
get { return _revision; }
}
public int Revision => _Revision;

/// <summary>
/// Gets the value of the build component of the version number for the current Version object.
/// </summary>
/// <value>The build version number.</value>
public int Build
{
get { return _build; }
}
public int Build => _Build;

/// <summary>
/// Returns a value indicating whether the current Version object is equal to a specified object.
Expand All @@ -101,7 +89,7 @@ public override bool Equals(Object obj)

var v = (Version)obj;
// check that major, minor, build & revision numbers match
return _major == v._major && _minor == v._minor && _build == v._build && _revision == v._revision;
return _Major == v._Major && _Minor == v._Minor && _Build == v._Build && _Revision == v._Revision;
}

/// <summary>
Expand All @@ -112,16 +100,35 @@ public override bool Equals(Object obj)
/// major.minor[.build[.revision]]</returns>
public override String ToString()
{
var retStr = _major + "." + _minor;
var retStr = _Major + "." + _Minor;

// Adds _Build and then _Revision if they are positive. They could be -1 in this case not added.
if (_build >= 0)
if (_Build >= 0)
{
retStr += "." + _build;
if (_revision >= 0) retStr += "." + _revision;
retStr += "." + _Build;
if (_Revision >= 0) retStr += "." + _Revision;
}

return retStr;
}

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
// Let's assume that most version numbers will be pretty small and just
// OR some lower order bits together.

int accumulator = 0;

accumulator |= (_Major & 0x0000000F) << 28;
accumulator |= (_Minor & 0x000000FF) << 20;
accumulator |= (_Build & 0x000000FF) << 12;
accumulator |= (_Revision & 0x00000FFF);

return accumulator;
}
}
}

0 comments on commit 1b6a37c

Please sign in to comment.