Is it good to have a GUID property in a class to use override in GetHashCode?
Sort of:
public class Voucher : IComparable<Voucher>, IComparable, IEquatable<Voucher> { private Guid? _guid; private Guid Guid { get { return _guid ?? (_guid = Guid.NewGuid()).GetValueOrDefault(); } } public int Id { get; private set; } public string Number { get; private set; } public DateTime Date { get; private set; } public Voucher(string number, DateTime date) { Number = number; Date = date; } public Voucher(int id, string number, DateTime date) : this(number, date) { Id = id; } public override bool Equals(object obj) { return Equals(obj as Voucher); } public override int GetHashCode() { return Guid.GetHashCode(); } public override string ToString() { return String.Format("[{0}] - [{1:dd/MM/yyyy}]", Number, Date); } #region IComparable<Voucher> Members public int CompareTo(Voucher other) { if (other == null) return -1; if (Date != other.Date) return Date.CompareTo(other.Date); else return Number.CompareTo(other.Number); } #endregion #region IComparable Members public int CompareTo(object obj) { return CompareTo(obj as Voucher); } #endregion #region IEquatable<Voucher> Members public bool Equals(Voucher other) { if (other != null) return (Number == other.Number) && (Date == other.Date); return false; } #endregion }
Yesterday I found out that in order to override GetHashCode, we should use only immutable members / fields of the class.
For many of my cases, this is just the ID created by the Sql server ID and for new instances that are 0.
So, for many new objects (not stored in the database, so Id is 0), the hash code of the object is the same. Right?
Will the solution use a GUID as an example above? Thanks.
EDIT Class after comments
So, after your comments, I changed it to:
public class Voucher : IComparable<Voucher>, IComparable, IEquatable<Voucher> { public int Id { get; private set; } public string Number { get; private set; } public DateTime Date { get; private set; } public Voucher(string number, DateTime date) { Number = number; Date = date; } public Voucher(int id, string number, DateTime date) : this(number, date) { Id = id; } public override bool Equals(object obj) { return Equals(obj as Voucher); } public override int GetHashCode() { return Number.GetHashCode() ^ Date.GetHashCode(); } public override string ToString() { return String.Format("[{0}] - [{1:dd/MM/yyyy}]", Number, Date); } #region IComparable<Voucher> Members public int CompareTo(Voucher other) { if (other == null) return -1; if (Date != other.Date) return Date.CompareTo(other.Date); else return Number.CompareTo(other.Number); } #endregion #region IComparable Members public int CompareTo(object obj) { return CompareTo(obj as Voucher); } #endregion #region IEquatable<Voucher> Members public bool Equals(Voucher other) { if (other != null) return (Number == other.Number) && (Date == other.Date); return false; } #endregion }
I assume this is normal, as the voucher is unchanged.
But if the members of Number and Date were not immutable and could be accessed - changed outside the class? Then what is the solution? Is it enough to just document a class like "Cannot be used in HashCode-dependent lists"?