Skip to content

Instantly share code, notes, and snippets.

@ronnieoverby
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ronnieoverby/68af3beccef3436d645d to your computer and use it in GitHub Desktop.
Save ronnieoverby/68af3beccef3436d645d to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
public class CharacterComparer : IEqualityComparer<char>, IEqualityComparer<string>
{
public static readonly CharacterComparer Ordinal = new CharacterComparer(StringComparer.Ordinal);
public static readonly CharacterComparer OrdinalIgnoreCase = new CharacterComparer(StringComparer.OrdinalIgnoreCase);
public static readonly CharacterComparer CurrentCulture = new CharacterComparer(StringComparer.CurrentCulture);
public static readonly CharacterComparer CurrentCultureIgnoreCase = new CharacterComparer(StringComparer.CurrentCultureIgnoreCase);
public static readonly CharacterComparer InvariantCulture = new CharacterComparer(StringComparer.InvariantCulture);
public static readonly CharacterComparer InvariantCultureIgnoreCase = new CharacterComparer(StringComparer.InvariantCultureIgnoreCase);
private readonly IEqualityComparer<char> _charComparer;
private readonly IEqualityComparer<string> _stringComparer;
public CharacterComparer(IEqualityComparer<string> stringComparer)
{
if (stringComparer == null) throw new ArgumentNullException("stringComparer");
var wrappingComparer = stringComparer as CharacterComparer;
if (wrappingComparer != null)
{
_stringComparer = wrappingComparer._stringComparer;
_charComparer = wrappingComparer._charComparer;
}
else
{
_stringComparer = stringComparer;
_charComparer = stringComparer as IEqualityComparer<char>;
}
}
public CharacterComparer(IEqualityComparer<char> charComparer)
{
if (charComparer == null) throw new ArgumentNullException("charComparer");
var wrappingComparer = charComparer as CharacterComparer;
if (wrappingComparer != null)
{
_stringComparer = wrappingComparer._stringComparer;
_charComparer = wrappingComparer._charComparer;
}
else
{
_charComparer = charComparer;
_stringComparer = charComparer as IEqualityComparer<string>;
}
}
public bool Equals(char x, char y)
{
if (_charComparer != null)
return _charComparer.Equals(x, y);
var s1 = x.ToString();
var s2 = y.ToString();
return _stringComparer.Equals(s1, s2);
}
public int GetHashCode(char c)
{
if (_charComparer != null)
return _charComparer.GetHashCode(c);
var s = c.ToString();
return _stringComparer.GetHashCode(s);
}
public bool Equals(string x, string y)
{
if (_stringComparer != null)
return _stringComparer.Equals(x, y);
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.Length != y.Length) return false;
var it1 = x.GetEnumerator();
var it2 = y.GetEnumerator();
while (true)
{
var m1 = it1.MoveNext();
var m2 = it2.MoveNext();
if (m1 ^ m2)
// should not be possible because of length check above
return false;
if (!m1)
return true;
if (!_charComparer.Equals(it1.Current, it2.Current))
return false;
}
}
public int GetHashCode(string s)
{
if (_stringComparer != null)
return _stringComparer.GetHashCode(s);
unchecked
{
var it = s.GetEnumerator();
if (!it.MoveNext())
return _charComparer.GetHashCode(default(char));
var hashCode = _charComparer.GetHashCode(it.Current);
while (it.MoveNext())
hashCode = (hashCode * 397) ^ _charComparer.GetHashCode(it.Current);
return hashCode;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment