Merge pull request #4198 from vkargov/vk-prevbb
[mono.git] / mcs / class / Mono.C5 / C5 / Hashers.cs
index d759c15a9f9f3b1e0cea099149abb4b0ba3d6769..2389239b76ca8875cff7259ea1d02f69685830fc 100644 (file)
-#if NET_2_0
-/*\r
- Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using C5;\r
-using System;\r
-using System.Reflection;\r
-using System.Reflection.Emit;\r
-using System.Diagnostics;\r
-using SCG = System.Collections.Generic;\r
-\r
-namespace C5\r
-{\r
-  /// <summary>\r
-  /// Utility class for building default generic equalityComparers.\r
-  /// </summary>\r
-  /// <typeparam name="T"></typeparam>\r
-  public static class EqualityComparer<T>\r
-  {\r
-    readonly static Type isequenced = typeof(ISequenced<>);\r
-\r
-    readonly static Type icollection = typeof(ICollection<>);\r
-\r
-    readonly static Type orderedcollectionequalityComparer = typeof(SequencedCollectionEqualityComparer<,>);\r
-\r
-    readonly static Type unorderedcollectionequalityComparer = typeof(UnsequencedCollectionEqualityComparer<,>);\r
-\r
-    readonly static Type equalityequalityComparer = typeof(EquatableEqualityComparer<>);\r
-\r
-    readonly static Type iequalitytype = typeof(IEquatable<T>);\r
-\r
-    static SCG.IEqualityComparer<T> cachedDefault = null;\r
-\r
-    //TODO: find the right word for initialized+invocation \r
-    /// <summary>\r
-    /// A default generic equalityComparer for type T. The procedure is as follows:\r
-    /// <list>\r
-    /// <item>If T is int, double, byte or char, \r
-    /// the equalityComparer will be a standard equalityComparer for that type</item>\r
-    /// <item>If the actual generic argument T implements the generic interface\r
-    /// <see cref="T:C5.ISequenced`1"/> for some value W of its generic parameter T,\r
-    /// the equalityComparer will be <see cref="T:C5.SequencedCollectionEqualityComparer`2"/></item>\r
-    /// <item>If the actual generic argument T implements \r
-    /// <see cref="T:C5.ICollectionValue`1"/> for some value W of its generic parameter T,\r
-    /// the equalityComparer will be <see cref="T:C5.UnsequencedCollectionEqualityComparer`2"/></item>\r
-    /// <item>If T is a type implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer\r
-    /// will be <see cref="T:C5.EquatableEqualityComparer`1"/></item>\r
-    /// <item>If T is a type not implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer\r
-    /// will be <see cref="T:C5.NaturalEqualityComparer`1"/> </item>\r
-    /// </list>   \r
-    /// The <see cref="T:C5.IEqualityComparer`1"/> object is constructed when this class is initialised, i.e. \r
-    /// its static constructors called. Thus, the property will be the same object \r
-    /// for the duration of an invocation of the runtime, but a value serialized in \r
-    /// another invocation and deserialized here will not be the same object.\r
-    /// </summary>\r
-    /// <value></value>\r
-    public static SCG.IEqualityComparer<T> Default\r
-    {\r
-      get\r
-      {\r
-        if (cachedDefault != null)\r
-          return cachedDefault;\r
-\r
-        Type t = typeof(T);\r
-\r
-        if (t.IsValueType)\r
-        {\r
-          if (t.Equals(typeof(int)))\r
-            return cachedDefault = (SCG.IEqualityComparer<T>)(IntEqualityComparer.Default);\r
-          else if (t.Equals(typeof(double)))\r
-            return cachedDefault = (SCG.IEqualityComparer<T>)(DoubleEqualityComparer.Default);\r
-          else if (t.Equals(typeof(byte)))\r
-            return cachedDefault = (SCG.IEqualityComparer<T>)(ByteEqualityComparer.Default);\r
-          else if (t.Equals(typeof(char)))\r
-            return cachedDefault = (SCG.IEqualityComparer<T>)(CharEqualityComparer.Default);\r
-        }\r
-        Type[] interfaces = t.GetInterfaces();\r
-        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(isequenced))\r
-          return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));\r
-        foreach (Type ty in interfaces)\r
-        {\r
-          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(isequenced))\r
-            return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));\r
-        }\r
-        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(icollection))\r
-          return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));\r
-        foreach (Type ty in interfaces)\r
-        {\r
-          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(icollection))\r
-            return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));\r
-        }\r
-        if (iequalitytype.IsAssignableFrom(t))\r
-          return createAndCache(equalityequalityComparer.MakeGenericType(new Type[] { t }));\r
-        else\r
-          return cachedDefault = NaturalEqualityComparer<T>.Default;\r
-      }\r
-    }\r
-    static SCG.IEqualityComparer<T> createAndCache(Type equalityComparertype)\r
-    {\r
-      return cachedDefault = (SCG.IEqualityComparer<T>)(equalityComparertype.GetProperty("Default", BindingFlags.Static | BindingFlags.Public).GetValue(null, null));\r
-    }\r
-  }\r
-\r
-  /// <summary>\r
-  /// A default item equalityComparer calling through to\r
-  /// the GetHashCode and Equals methods inherited from System.Object.\r
-  /// </summary>\r
-  public sealed class NaturalEqualityComparer<T> : SCG.IEqualityComparer<T>\r
-  {\r
-    static NaturalEqualityComparer<T> cached;\r
-    NaturalEqualityComparer() { }\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <value></value>\r
-    public static NaturalEqualityComparer<T> Default { get { return cached ?? (cached = new NaturalEqualityComparer<T>()); } }\r
-    //TODO: check if null check is reasonable\r
-    //Answer: if we have struct C<T> { T t; int i;} and implement GetHashCode as\r
-    //the sum of hashcodes, and T may be any type, we cannot make the null check \r
-    //inside the definition of C<T> in a reasonable way.\r
-    /// <summary>\r
-    /// Get the hash code with respect to this item equalityComparer\r
-    /// </summary>\r
-    /// <param name="item">The item</param>\r
-    /// <returns>The hash code</returns>\r
-    [Tested]\r
-    public int GetHashCode(T item) { return item == null ? 0 : item.GetHashCode(); }\r
-\r
-\r
-    /// <summary>\r
-    /// Check if two items are equal with respect to this item equalityComparer\r
-    /// </summary>\r
-    /// <param name="item1">first item</param>\r
-    /// <param name="item2">second item</param>\r
-    /// <returns>True if equal</returns>\r
-    [Tested]\r
-    public bool Equals(T item1, T item2)\r
-    {\r
-      return item1 == null ? item2 == null : item1.Equals(item2);\r
-    }\r
-  }\r
-\r
-  /// <summary>\r
-  /// A default equalityComparer for a type, T, implementing <see cref="T:C5.IEquatable`1"/>. \r
-  /// \r
-  /// The equalityComparer forwards calls to GetHashCode and Equals to the methods \r
-  /// on T. The point is that it is Equals(T) and not Equals(object)\r
-  /// that is called. This will save a boxing/unboxing pair if T is a value type\r
-  /// and in general a runtime type check.\r
-  /// </summary>\r
-  /// <typeparam name="T"></typeparam>\r
-  public class EquatableEqualityComparer<T> : SCG.IEqualityComparer<T> where T : IEquatable<T>\r
-  {\r
-    static EquatableEqualityComparer<T> cached = new EquatableEqualityComparer<T>();\r
-    EquatableEqualityComparer() { }\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <value></value>\r
-    public static EquatableEqualityComparer<T> Default { get { return cached ?? (cached = new EquatableEqualityComparer<T>()); } }\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <param name="item"></param>\r
-    /// <returns></returns>\r
-    public int GetHashCode(T item) { return item == null ? 0 : item.GetHashCode(); }\r
-\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <param name="item1"></param>\r
-    /// <param name="item2"></param>\r
-    /// <returns></returns>\r
-    public bool Equals(T item1, T item2) { return item1 == null ? item2 == null : item1.Equals(item2); }\r
-  }\r
-\r
-  /// <summary>\r
-  /// A equalityComparer for a reference type that uses reference equality for equality and the hash code from object as hash code.\r
-  /// </summary>\r
-  /// <typeparam name="T">The item type. Must be a reference type.</typeparam>\r
-  public class ReferenceEqualityComparer<T> : SCG.IEqualityComparer<T> where T : class\r
-  {\r
-    static ReferenceEqualityComparer<T> cached;\r
-    ReferenceEqualityComparer() { }\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <value></value>\r
-    public static ReferenceEqualityComparer<T> Default { get { return cached ?? (cached = new ReferenceEqualityComparer<T>()); } }\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <param name="item"></param>\r
-    /// <returns></returns>\r
-    public int GetHashCode(T item)\r
-    {\r
-      return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(item);\r
-    }\r
-\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <param name="i1"></param>\r
-    /// <param name="i2"></param>\r
-    /// <returns></returns>\r
-    public bool Equals(T i1, T i2)\r
-    {\r
-      return object.ReferenceEquals(i1, i2);\r
-    }\r
-  }\r
-\r
-  /// <summary>\r
-  /// An equalityComparer compatible with a given comparer. All hash codes are 0, \r
-  /// meaning that anything based on hash codes will be quite inefficient.\r
-  /// <para><b>Note: this will give a new EqualityComparer each time created!</b></para>\r
-  /// </summary>\r
-  /// <typeparam name="T"></typeparam>\r
-  public class ComparerZeroHashCodeEqualityComparer<T> : SCG.IEqualityComparer<T>\r
-  {\r
-    SCG.IComparer<T> comparer;\r
-    /// <summary>\r
-    /// Create a trivial <see cref="T:C5.IEqualityComparer`1"/> compatible with the \r
-    /// <see cref="T:C5.IComparer`1"/> <code>comparer</code>\r
-    /// </summary>\r
-    /// <param name="comparer"></param>\r
-    public ComparerZeroHashCodeEqualityComparer(SCG.IComparer<T> comparer)\r
-    {\r
-      if (comparer == null)\r
-        throw new NullReferenceException("Compaer cannot be null");\r
-      this.comparer = comparer;\r
-    }\r
-    /// <summary>\r
-    /// A trivial, inefficient hash fuction. Compatible with any equality relation.\r
-    /// </summary>\r
-    /// <param name="item"></param>\r
-    /// <returns>0</returns>\r
-    public int GetHashCode(T item) { return 0; }\r
-    /// <summary>\r
-    /// Equality of two items as defined by the comparer.\r
-    /// </summary>\r
-    /// <param name="item1"></param>\r
-    /// <param name="item2"></param>\r
-    /// <returns></returns>\r
-    public bool Equals(T item1, T item2) { return comparer.Compare(item1, item2) == 0; }\r
-  }\r
-\r
-  /// <summary>\r
-  /// Prototype for an sequenced equalityComparer for something (T) that implements ISequenced[W]\r
-  /// This will use ISequenced[W] specific implementations of the equalityComparer operations\r
-  /// </summary>\r
-  /// <typeparam name="T"></typeparam>\r
-  /// <typeparam name="W"></typeparam>\r
-  public class SequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>\r
-      where T : ISequenced<W>\r
-  {\r
-    static SequencedCollectionEqualityComparer<T, W> cached;\r
-    SequencedCollectionEqualityComparer() { }\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <value></value>\r
-    public static SequencedCollectionEqualityComparer<T, W> Default { get { return cached ?? (cached = new SequencedCollectionEqualityComparer<T, W>()); } }\r
-    /// <summary>\r
-    /// Get the hash code with respect to this sequenced equalityComparer\r
-    /// </summary>\r
-    /// <param name="collection">The collection</param>\r
-    /// <returns>The hash code</returns>\r
-    [Tested]\r
-    public int GetHashCode(T collection) { return collection.GetSequencedHashCode(); }\r
-\r
-\r
-    /// <summary>\r
-    /// Check if two items are equal with respect to this sequenced equalityComparer\r
-    /// </summary>\r
-    /// <param name="collection1">first collection</param>\r
-    /// <param name="collection2">second collection</param>\r
-    /// <returns>True if equal</returns>\r
-    [Tested]\r
-    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.SequencedEquals(collection2); }\r
-  }\r
-\r
-  /// <summary>\r
-  /// Prototype for an unsequenced equalityComparer for something (T) that implements ICollection[W]\r
-  /// This will use ICollection[W] specific implementations of the equalityComparer operations\r
-  /// </summary>\r
-  /// <typeparam name="T"></typeparam>\r
-  /// <typeparam name="W"></typeparam>\r
-  public class UnsequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>\r
-      where T : ICollection<W>\r
-  {\r
-    static UnsequencedCollectionEqualityComparer<T, W> cached;\r
-    UnsequencedCollectionEqualityComparer() { }\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <value></value>\r
-    public static UnsequencedCollectionEqualityComparer<T, W> Default { get { return cached ?? (cached = new UnsequencedCollectionEqualityComparer<T, W>()); } }\r
-    /// <summary>\r
-    /// Get the hash code with respect to this unsequenced equalityComparer\r
-    /// </summary>\r
-    /// <param name="collection">The collection</param>\r
-    /// <returns>The hash code</returns>\r
-    [Tested]\r
-    public int GetHashCode(T collection) { return collection.GetUnsequencedHashCode(); }\r
-\r
-\r
-    /// <summary>\r
-    /// Check if two collections are equal with respect to this unsequenced equalityComparer\r
-    /// </summary>\r
-    /// <param name="collection1">first collection</param>\r
-    /// <param name="collection2">second collection</param>\r
-    /// <returns>True if equal</returns>\r
-    [Tested]\r
-    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.UnsequencedEquals(collection2); }\r
-  }\r
-\r
-}\r
-\r
-\r
-\r
-\r
-\r
-#if EXPERIMENTAL\r
-namespace C5.EqualityComparerBuilder\r
-{\r
-\r
-  /// <summary>\r
-  /// IEqualityComparer factory class: examines at instatiation time if T is an\r
-  /// interface implementing "int GetHashCode()" and "bool Equals(T)".\r
-  /// If those are not present, MakeEqualityComparer will return a default equalityComparer,\r
-  /// else this class will implement IequalityComparer[T] via Invoke() on the\r
-  /// reflected method infos.\r
-  /// </summary>\r
-  public class ByInvoke<T> : SCG.IEqualityComparer<T>\r
-  {\r
-    internal static readonly System.Reflection.MethodInfo hinfo, einfo;\r
-\r
-\r
-    static ByInvoke()\r
-    {\r
-      Type t = typeof(T);\r
-\r
-      if (!t.IsInterface) return;\r
-\r
-      BindingFlags f = BindingFlags.Public | BindingFlags.Instance;\r
-\r
-      hinfo = t.GetMethod("GetHashCode", f, null, new Type[0], null);\r
-      einfo = t.GetMethod("Equals", f, null, new Type[1] { t }, null);\r
-    }\r
-\r
-\r
-    private ByInvoke() { }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <returns></returns>\r
-    public static SCG.IEqualityComparer<T> MakeEqualityComparer()\r
-    {\r
-      if (hinfo != null && einfo != null)\r
-        return new ByInvoke<T>();\r
-      else\r
-        return NaturalEqualityComparer<T>.Default;\r
-    }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <param name="item"></param>\r
-/// <returns></returns>\r
-    public int GetHashCode(T item)\r
-    {\r
-      return (int)(hinfo.Invoke(item, null));\r
-    }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <param name="i1"></param>\r
-/// <param name="i2"></param>\r
-/// <returns></returns>\r
-    public bool Equals(T i1, T i2)\r
-    {\r
-      return (bool)(einfo.Invoke(i1, new object[1] { i2 }));\r
-    }\r
-  }\r
-\r
-\r
-\r
-  /// <summary>\r
-  /// Like ByInvoke, but tries to build a equalityComparer by RTCG to\r
-  /// avoid the Invoke() overhead. \r
-  /// </summary>\r
-  public class ByRTCG\r
-  {\r
-    private static ModuleBuilder moduleBuilder;\r
-\r
-    private static AssemblyBuilder assemblyBuilder;\r
-\r
-    /// <summary>\r
-    /// \r
-    /// </summary>\r
-    /// <param name="hinfo"></param>\r
-    /// <param name="einfo"></param>\r
-    /// <returns></returns>\r
-    public static SCG.IEqualityComparer<T> CreateEqualityComparer<T>(MethodInfo hinfo, MethodInfo einfo)\r
-    {\r
-      if (moduleBuilder == null)\r
-      {\r
-        string assmname = "LeFake";\r
-        string filename = assmname + ".dll";\r
-        AssemblyName assemblyName = new AssemblyName("LeFake");\r
-        AppDomain appdomain = AppDomain.CurrentDomain;\r
-        AssemblyBuilderAccess acc = AssemblyBuilderAccess.RunAndSave;\r
-\r
-        assemblyBuilder = appdomain.DefineDynamicAssembly(assemblyName, acc);\r
-        moduleBuilder = assemblyBuilder.DefineDynamicModule(assmname, filename);\r
-      }\r
-\r
-      Type t = typeof(T);\r
-      Type o_t = typeof(object);\r
-      Type h_t = typeof(SCG.IEqualityComparer<T>);\r
-      Type i_t = typeof(int);\r
-      //TODO: protect uid for thread safety!\r
-      string name = "C5.Dynamic.EqualityComparer_" + Guid.NewGuid().ToString();\r
-      TypeAttributes tatt = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;\r
-      TypeBuilder tb = moduleBuilder.DefineType(name, tatt, o_t, new Type[1] { h_t });\r
-      MethodAttributes matt = MethodAttributes.Public | MethodAttributes.Virtual;\r
-      MethodBuilder mb = tb.DefineMethod("GetHashCode", matt, i_t, new Type[1] { t });\r
-      ILGenerator ilg = mb.GetILGenerator();\r
-\r
-      ilg.Emit(OpCodes.Ldarg_1);\r
-      ilg.Emit(OpCodes.Callvirt, hinfo);\r
-      ilg.Emit(OpCodes.Ret);\r
-      mb = tb.DefineMethod("Equals", matt, typeof(bool), new Type[2] { t, t });\r
-      ilg = mb.GetILGenerator();\r
-      ilg.Emit(OpCodes.Ldarg_1);\r
-      ilg.Emit(OpCodes.Ldarg_2);\r
-      ilg.Emit(OpCodes.Callvirt, einfo);\r
-      ilg.Emit(OpCodes.Ret);\r
-\r
-      Type equalityComparer_t = tb.CreateType();\r
-      object equalityComparer = equalityComparer_t.GetConstructor(new Type[0]).Invoke(null);\r
-\r
-      return (SCG.IEqualityComparer<T>)equalityComparer;\r
-    }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <typeparam name="T"></typeparam>\r
-/// <returns></returns>\r
-    public static SCG.IEqualityComparer<T> build<T>()\r
-    {\r
-      MethodInfo hinfo = ByInvoke<T>.hinfo, einfo = ByInvoke<T>.einfo;\r
-\r
-      if (hinfo != null && einfo != null)\r
-        return CreateEqualityComparer<T>(hinfo, einfo);\r
-      else\r
-        return EqualityComparer<T>.Default;\r
-    }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-    public void dump()\r
-    {\r
-      assemblyBuilder.Save("LeFake.dll");\r
-    }\r
-  }\r
-}\r
-#endif\r
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
 
+using C5;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// Utility class for building default generic equalityComparers.
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public static class EqualityComparer<T>
+  {
+    readonly static Type isequenced = typeof(ISequenced<>);
+
+    readonly static Type icollection = typeof(ICollection<>);
+
+    readonly static Type orderedcollectionequalityComparer = typeof(SequencedCollectionEqualityComparer<,>);
+
+    readonly static Type unorderedcollectionequalityComparer = typeof(UnsequencedCollectionEqualityComparer<,>);
+
+    readonly static Type equalityequalityComparer = typeof(EquatableEqualityComparer<>);
+
+    readonly static Type iequalitytype = typeof(IEquatable<T>);
+
+    static SCG.IEqualityComparer<T> cachedDefault = null;
+
+    //TODO: find the right word for initialized+invocation 
+    /// <summary>
+    /// A default generic equality comparer for type T. The procedure is as follows:
+    /// <list>
+    /// <item>If T is a primitive type (char, sbyte, byte, short, ushort, int, uint, float, double, decimal), 
+    /// the equalityComparer will be a standard equalityComparer for that type</item>
+    /// <item>If the actual generic argument T implements the generic interface
+    /// <see cref="T:C5.ISequenced`1"/> for some value W of its generic parameter T,
+    /// the equalityComparer will be <see cref="T:C5.SequencedCollectionEqualityComparer`2"/></item>
+    /// <item>If the actual generic argument T implements 
+    /// <see cref="T:C5.ICollection`1"/> for some value W of its generic parameter T,
+    /// the equalityComparer will be <see cref="T:C5.UnsequencedCollectionEqualityComparer`2"/></item>
+    /// <item>If T is a type implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer
+    /// will be <see cref="T:C5.EquatableEqualityComparer`1"/></item>
+    /// <item>If T is a type not implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer
+    /// will be <see cref="T:C5.NaturalEqualityComparer`1"/> </item>
+    /// </list>   
+    /// The <see cref="T:C5.IEqualityComparer`1"/> object is constructed when this class is initialised, i.e. 
+    /// its static constructors called. Thus, the property will be the same object 
+    /// for the duration of an invocation of the runtime, but a value serialized in 
+    /// another invocation and deserialized here will not be the same object.
+    /// </summary>
+    /// <value></value>
+    public static SCG.IEqualityComparer<T> Default
+    {
+      get
+      {
+        if (cachedDefault != null)
+          return cachedDefault;
+
+        Type t = typeof(T);
+
+        if (t.IsValueType)
+        {
+          if (t.Equals(typeof(char)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(CharEqualityComparer.Default);
+
+          if (t.Equals(typeof(sbyte)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(SByteEqualityComparer.Default);
+
+          if (t.Equals(typeof(byte)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(ByteEqualityComparer.Default);
+
+          if (t.Equals(typeof(short)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(ShortEqualityComparer.Default);
+
+          if (t.Equals(typeof(ushort)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(UShortEqualityComparer.Default);
+          
+          if (t.Equals(typeof(int)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(IntEqualityComparer.Default);
+
+          if (t.Equals(typeof(uint)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(UIntEqualityComparer.Default);
+
+          if (t.Equals(typeof(long)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(LongEqualityComparer.Default);
+
+          if (t.Equals(typeof(ulong)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(ULongEqualityComparer.Default);
+
+          if (t.Equals(typeof(float)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(FloatEqualityComparer.Default);
+          
+          if (t.Equals(typeof(double)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(DoubleEqualityComparer.Default);
+
+          if (t.Equals(typeof(decimal)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(DecimalEqualityComparer.Default);
+        }
+        Type[] interfaces = t.GetInterfaces();
+        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(isequenced))
+          return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));
+        foreach (Type ty in interfaces)
+        {
+          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(isequenced))
+            return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));
+        }
+        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(icollection))
+          return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));
+        foreach (Type ty in interfaces)
+        {
+          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(icollection))
+            return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));
+        }
+        if (iequalitytype.IsAssignableFrom(t))
+          return createAndCache(equalityequalityComparer.MakeGenericType(new Type[] { t }));
+        else
+          return cachedDefault = NaturalEqualityComparer<T>.Default;
+      }
+    }
+    static SCG.IEqualityComparer<T> createAndCache(Type equalityComparertype)
+    {
+      return cachedDefault = (SCG.IEqualityComparer<T>)(equalityComparertype.GetProperty("Default", BindingFlags.Static | BindingFlags.Public).GetValue(null, null));
+    }
+  }
+
+  /// <summary>
+  /// A default item equalityComparer calling through to
+  /// the GetHashCode and Equals methods inherited from System.Object.
+  /// </summary>
+  [Serializable]
+  public sealed class NaturalEqualityComparer<T> : SCG.IEqualityComparer<T>
+  {
+    static NaturalEqualityComparer<T> cached;
+    NaturalEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static NaturalEqualityComparer<T> Default { get { return cached ?? (cached = new NaturalEqualityComparer<T>()); } }
+    //TODO: check if null check is reasonable
+    //Answer: if we have struct C<T> { T t; int i;} and implement GetHashCode as
+    //the sum of hashcodes, and T may be any type, we cannot make the null check 
+    //inside the definition of C<T> in a reasonable way.
+    /// <summary>
+    /// Get the hash code with respect to this item equalityComparer
+    /// </summary>
+    /// <param name="item">The item</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(T item) { return item == null ? 0 : item.GetHashCode(); }
+
+    /// <summary>
+    /// Check if two items are equal with respect to this item equalityComparer
+    /// </summary>
+    /// <param name="item1">first item</param>
+    /// <param name="item2">second item</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(T item1, T item2)
+    {
+      return item1 == null ? item2 == null : item1.Equals(item2);
+    }
+  }
+
+  /// <summary>
+  /// A default equality comparer for a type T that implements System.IEquatable<typeparamref name="T"/>. 
+  /// 
+  /// The equality comparer forwards calls to GetHashCode and Equals to the IEquatable methods 
+  /// on T, so Equals(T) is called, not Equals(object). 
+  /// This will save boxing abd unboxing if T is a value type
+  /// and in general saves a runtime type check.
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public class EquatableEqualityComparer<T> : SCG.IEqualityComparer<T> where T : IEquatable<T>
+  {
+    static EquatableEqualityComparer<T> cached = new EquatableEqualityComparer<T>();
+    EquatableEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static EquatableEqualityComparer<T> Default { 
+      get { return cached ?? (cached = new EquatableEqualityComparer<T>()); } 
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int GetHashCode(T item) { return item == null ? 0 : item.GetHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item1"></param>
+    /// <param name="item2"></param>
+    /// <returns></returns>
+    public bool Equals(T item1, T item2) { return item1 == null ? item2 == null : item1.Equals(item2); }
+  }
+
+  /// <summary>
+  /// A equalityComparer for a reference type that uses reference equality for equality and the hash code from object as hash code.
+  /// </summary>
+  /// <typeparam name="T">The item type. Must be a reference type.</typeparam>
+  [Serializable]
+  public class ReferenceEqualityComparer<T> : SCG.IEqualityComparer<T> where T : class
+  {
+    static ReferenceEqualityComparer<T> cached;
+    ReferenceEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static ReferenceEqualityComparer<T> Default { 
+      get { return cached ?? (cached = new ReferenceEqualityComparer<T>()); } 
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int GetHashCode(T item)
+    {
+      return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(item);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="i1"></param>
+    /// <param name="i2"></param>
+    /// <returns></returns>
+    public bool Equals(T i1, T i2)
+    {
+      return object.ReferenceEquals(i1, i2);
+    }
+  }
+
+  /// <summary>
+  /// An equalityComparer compatible with a given comparer. All hash codes are 0, 
+  /// meaning that anything based on hash codes will be quite inefficient.
+  /// <para><b>Note: this will give a new EqualityComparer each time created!</b></para>
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public class ComparerZeroHashCodeEqualityComparer<T> : SCG.IEqualityComparer<T>
+  {
+    SCG.IComparer<T> comparer;
+    /// <summary>
+    /// Create a trivial <see cref="T:C5.IEqualityComparer`1"/> compatible with the 
+    /// <see cref="T:C5.IComparer`1"/> <code>comparer</code>
+    /// </summary>
+    /// <param name="comparer"></param>
+    public ComparerZeroHashCodeEqualityComparer(SCG.IComparer<T> comparer)
+    {
+      if (comparer == null)
+        throw new NullReferenceException("Comparer cannot be null");
+      this.comparer = comparer;
+    }
+    /// <summary>
+    /// A trivial, inefficient hash fuction. Compatible with any equality relation.
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns>0</returns>
+    public int GetHashCode(T item) { return 0; }
+    /// <summary>
+    /// Equality of two items as defined by the comparer.
+    /// </summary>
+    /// <param name="item1"></param>
+    /// <param name="item2"></param>
+    /// <returns></returns>
+    public bool Equals(T item1, T item2) { return comparer.Compare(item1, item2) == 0; }
+  }
+
+  /// <summary>
+  /// Prototype for a sequenced equalityComparer for something (T) that implements ISequenced[W].
+  /// This will use ISequenced[W] specific implementations of the equality comparer operations.
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  /// <typeparam name="W"></typeparam>
+  [Serializable]
+  public class SequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>
+      where T : ISequenced<W>
+  {
+    static SequencedCollectionEqualityComparer<T, W> cached;
+    SequencedCollectionEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static SequencedCollectionEqualityComparer<T, W> Default { 
+      get { return cached ?? (cached = new SequencedCollectionEqualityComparer<T, W>()); } 
+    }
+    /// <summary>
+    /// Get the hash code with respect to this sequenced equalityComparer
+    /// </summary>
+    /// <param name="collection">The collection</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(T collection) { return collection.GetSequencedHashCode(); }
+
+    /// <summary>
+    /// Check if two items are equal with respect to this sequenced equalityComparer
+    /// </summary>
+    /// <param name="collection1">first collection</param>
+    /// <param name="collection2">second collection</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.SequencedEquals(collection2); }
+  }
+
+  /// <summary>
+  /// Prototype for an unsequenced equalityComparer for something (T) that implements ICollection[W]
+  /// This will use ICollection[W] specific implementations of the equalityComparer operations
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  /// <typeparam name="W"></typeparam>
+  [Serializable]
+  public class UnsequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>
+      where T : ICollection<W>
+  {
+    static UnsequencedCollectionEqualityComparer<T, W> cached;
+    UnsequencedCollectionEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static UnsequencedCollectionEqualityComparer<T, W> Default { get { return cached ?? (cached = new UnsequencedCollectionEqualityComparer<T, W>()); } }
+    /// <summary>
+    /// Get the hash code with respect to this unsequenced equalityComparer
+    /// </summary>
+    /// <param name="collection">The collection</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(T collection) { return collection.GetUnsequencedHashCode(); }
+
+
+    /// <summary>
+    /// Check if two collections are equal with respect to this unsequenced equalityComparer
+    /// </summary>
+    /// <param name="collection1">first collection</param>
+    /// <param name="collection2">second collection</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.UnsequencedEquals(collection2); }
+  }
+
+}
+
+
+#if EXPERIMENTAL
+namespace C5.EqualityComparerBuilder
+{
+
+  /// <summary>
+  /// IEqualityComparer factory class: examines at instatiation time if T is an
+  /// interface implementing "int GetHashCode()" and "bool Equals(T)".
+  /// If those are not present, MakeEqualityComparer will return a default equalityComparer,
+  /// else this class will implement IequalityComparer[T] via Invoke() on the
+  /// reflected method infos.
+  /// </summary>
+  public class ByInvoke<T> : SCG.IEqualityComparer<T>
+  {
+    internal static readonly System.Reflection.MethodInfo hinfo, einfo;
+
+
+    static ByInvoke()
+    {
+      Type t = typeof(T);
+
+      if (!t.IsInterface) return;
+
+      BindingFlags f = BindingFlags.Public | BindingFlags.Instance;
+
+      hinfo = t.GetMethod("GetHashCode", f, null, new Type[0], null);
+      einfo = t.GetMethod("Equals", f, null, new Type[1] { t }, null);
+    }
+
+
+    private ByInvoke() { }
+
+/// <summary>
+/// 
+/// </summary>
+/// <returns></returns>
+    public static SCG.IEqualityComparer<T> MakeEqualityComparer()
+    {
+      if (hinfo != null && einfo != null)
+        return new ByInvoke<T>();
+      else
+        return NaturalEqualityComparer<T>.Default;
+    }
+
+/// <summary>
+/// 
+/// </summary>
+/// <param name="item"></param>
+/// <returns></returns>
+    public int GetHashCode(T item)
+    {
+      return (int)(hinfo.Invoke(item, null));
+    }
+
+/// <summary>
+/// 
+/// </summary>
+/// <param name="i1"></param>
+/// <param name="i2"></param>
+/// <returns></returns>
+    public bool Equals(T i1, T i2)
+    {
+      return (bool)(einfo.Invoke(i1, new object[1] { i2 }));
+    }
+  }
+
+
+
+  /// <summary>
+  /// Like ByInvoke, but tries to build a equalityComparer by RTCG to
+  /// avoid the Invoke() overhead. 
+  /// </summary>
+  public class ByRTCG
+  {
+    private static ModuleBuilder moduleBuilder;
+
+    private static AssemblyBuilder assemblyBuilder;
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="hinfo"></param>
+    /// <param name="einfo"></param>
+    /// <returns></returns>
+    public static SCG.IEqualityComparer<T> CreateEqualityComparer<T>(MethodInfo hinfo, MethodInfo einfo)
+    {
+      if (moduleBuilder == null)
+      {
+        string assmname = "LeFake";
+        string filename = assmname + ".dll";
+        AssemblyName assemblyName = new AssemblyName("LeFake");
+        AppDomain appdomain = AppDomain.CurrentDomain;
+        AssemblyBuilderAccess acc = AssemblyBuilderAccess.RunAndSave;
+
+        assemblyBuilder = appdomain.DefineDynamicAssembly(assemblyName, acc);
+        moduleBuilder = assemblyBuilder.DefineDynamicModule(assmname, filename);
+      }
+
+      Type t = typeof(T);
+      Type o_t = typeof(object);
+      Type h_t = typeof(SCG.IEqualityComparer<T>);
+      Type i_t = typeof(int);
+      //TODO: protect uid for thread safety!
+      string name = "C5.Dynamic.EqualityComparer_" + Guid.NewGuid().ToString();
+      TypeAttributes tatt = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
+      TypeBuilder tb = moduleBuilder.DefineType(name, tatt, o_t, new Type[1] { h_t });
+      MethodAttributes matt = MethodAttributes.Public | MethodAttributes.Virtual;
+      MethodBuilder mb = tb.DefineMethod("GetHashCode", matt, i_t, new Type[1] { t });
+      ILGenerator ilg = mb.GetILGenerator();
+
+      ilg.Emit(OpCodes.Ldarg_1);
+      ilg.Emit(OpCodes.Callvirt, hinfo);
+      ilg.Emit(OpCodes.Ret);
+      mb = tb.DefineMethod("Equals", matt, typeof(bool), new Type[2] { t, t });
+      ilg = mb.GetILGenerator();
+      ilg.Emit(OpCodes.Ldarg_1);
+      ilg.Emit(OpCodes.Ldarg_2);
+      ilg.Emit(OpCodes.Callvirt, einfo);
+      ilg.Emit(OpCodes.Ret);
+
+      Type equalityComparer_t = tb.CreateType();
+      object equalityComparer = equalityComparer_t.GetConstructor(new Type[0]).Invoke(null);
+
+      return (SCG.IEqualityComparer<T>)equalityComparer;
+    }
+
+/// <summary>
+/// 
+/// </summary>
+/// <typeparam name="T"></typeparam>
+/// <returns></returns>
+    public static SCG.IEqualityComparer<T> build<T>()
+    {
+      MethodInfo hinfo = ByInvoke<T>.hinfo, einfo = ByInvoke<T>.einfo;
+
+      if (hinfo != null && einfo != null)
+        return CreateEqualityComparer<T>(hinfo, einfo);
+      else
+        return EqualityComparer<T>.Default;
+    }
+
+/// <summary>
+/// 
+/// </summary>
+    public void dump()
+    {
+      assemblyBuilder.Save("LeFake.dll");
+    }
+  }
+}
 #endif