Big Comparer Class
Includes: IBigEqualityComparer.cs
using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; [Serializable] public class BigComparer<T> : IBigEqualityComparer<T> { private static Type _type = typeof(T); private readonly BinaryFormatter _bf = new BinaryFormatter(); private readonly bool _isPrimitive; private readonly MemoryStream _ms = new MemoryStream(); private bool _disposed; public BigComparer() { _isPrimitive = IsPrimitive(); } public bool Equals(T x, T y) { if (x == null || y == null) return false; if (_isPrimitive) return x.Equals(y); if (_type == null) _type = x.GetType(); if (_type.IsArray) { if (!_isPrimitive) { var xb = GetBytesObjectSerial(x); var yb = GetBytesObjectSerial(y); return xb.Compare(yb); } else { var xb = GetBytesObject(x); var yb = GetBytesObject(y); return xb.Compare(yb); } } return x.Equals(y); } public long GetHashCode(T obj) { if (_isPrimitive) return obj.GetHashCode(); if (_type == null) _type = obj.GetType(); var result = 0xCBF29CE484222325; byte[] buf; buf = !_isPrimitive ? GetBytesObjectSerial(obj) : GetBytesObject(obj); foreach (var b in buf) result = (result ^ b) * 0x100000001B3; return (long) result; } private void Dispose(bool disposing) { if (!_disposed) if (disposing) _ms?.Close(); _disposed = true; } public byte[] GetBytesObjectSerial(object value) { if (_type == null) _type = value.GetType(); if (!_type.IsSerializable) throw new Exception("Error: Object is not Serializable."); _ms.SetLength(0); _bf.Serialize(_ms, value); return _ms.ToArray().SubArray(0, (int) _ms.Length); } public bool IsPrimitive() { if (_type == null) _type = typeof(T); switch (Type.GetTypeCode(_type)) { case TypeCode.Boolean: case TypeCode.Char: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Single: case TypeCode.String: case TypeCode.Decimal: case TypeCode.DateTime: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Double: return true; default: return false; } } public byte[] GetBytesObject(object obj) { if (_type == null) _type = obj.GetType(); switch (_type.Name.Trim('[', ']')) { case "Byte": return !_type.IsArray ? new[] {(byte) obj} : (byte[]) obj; case "Boolean": return !_type.IsArray ? ((bool) obj).GetBytes() : ((bool[]) obj).GetBytes(); case "SByte": return !_type.IsArray ? ((sbyte) obj).GetBytes() : ((sbyte[]) obj).GetBytes(); case "Char": return !_type.IsArray ? ((char) obj).GetBytes() : ((char[]) obj).GetBytes(); case "Int16": return !_type.IsArray ? ((short) obj).GetBytes() : ((short[]) obj).GetBytes(); case "UInt16": return !_type.IsArray ? ((ushort) obj).GetBytes() : ((ushort[]) obj).GetBytes(); case "Int32": return !_type.IsArray ? ((int) obj).GetBytes() : ((int[]) obj).GetBytes(); case "UInt32": return !_type.IsArray ? ((uint) obj).GetBytes() : ((uint[]) obj).GetBytes(); case "Int64": return !_type.IsArray ? ((long) obj).GetBytes() : ((long[]) obj).GetBytes(); case "UInt64": return !_type.IsArray ? ((ulong) obj).GetBytes() : ((ulong[]) obj).GetBytes(); case "Single": return !_type.IsArray ? ((float) obj).GetBytes() : ((float[]) obj).GetBytes(); case "Double": return !_type.IsArray ? ((double) obj).GetBytes() : ((double[]) obj).GetBytes(); case "String": return !_type.IsArray ? ((string) obj).GetBytes() : ((string[]) obj).GetBytes(); case "Decimal": return !_type.IsArray ? ((decimal) obj).GetBytes() : ((decimal[]) obj).GetBytes(); case "DateTime": return !_type.IsArray ? ((DateTime) obj).GetBytes() : ((DateTime[]) obj).GetBytes(); } return GetBytesObjectSerial(obj); } } public interface IBigEqualityComparer<in T> { bool Equals(T x, T y); long GetHashCode(T obj); } public interface IBigEqualityComparer32<in T> { bool Equals(T x, T y); int GetHashCode(T obj); }