I'd say (based on my understanding of your example), something like this. You could include a more complex hash code that parallels your FileDate vs CRC32, but really since the common glue is always the FileName you could just use that as your surrogate hash code.
Remember, Equal() objects should never have different hash codes, but !Equal() objects may have the same one (it's just a potential collision).
Also you'll want to be careful about the fields that are part of the hash code being mutable, otherwise the hash code of the object can "change" which could be very bad in a Dictionary...
public sealed class Symbol : IEquatable<Symbol>
{
public string FileName { get; set; }
public DateTime FileDate { get; set; }
public long CRC32 { get; set; }
public bool Equals(Symbol other)
{
if (other == null)
{
return false;
}
return FileName == other.FileName &&
(FileDate == other.FileDate || CRC32 == other.CRC32);
}
public override bool Equals(object obj)
{
return Equals(obj as Symbol);
}
public override int GetHashCode()
{
// since FileName must be equal (others may or may not)
// can use its hash code as your surrogate hash code.
return FileName.GetHashCode();
}
}
overrideofEquals()?