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);
}