Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / corlib / System / Tuples.cs
index 5756fa2684379f0310c0a70c9345e32f92cdf161..a9631dbbdaf01de52c7fe1d8c201fbc60bc1d72f 100644 (file)
@@ -27,7 +27,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if MOONLIGHT || NET_4_0
+#if NET_4_0
 
 using System;
 using System.Collections;
@@ -48,23 +48,20 @@ namespace System
                        this.item7 = item7;
                        this.rest = rest;
 
-                       bool ok = true;
-                       if (!typeof (TRest).IsGenericType)
-                               ok = false;
-                       if (ok) {
-                               Type t = typeof (TRest).GetGenericTypeDefinition ();
-                               if (!(t == typeof (Tuple<>) || t == typeof (Tuple<,>) || t == typeof (Tuple<,,>) || t == typeof (Tuple<,,,>) || t == typeof (Tuple<,,,,>) || t == typeof (Tuple <,,,,,>) || t == typeof (Tuple<,,,,,,>) || t == typeof (Tuple<,,,,,,,>)))
-                                       ok = false;
-                       }
-                       if (!ok)
-                               throw new ArgumentException ("The last element of an eight element tuple must be a Tuple.");
+                       if (!(rest is ITuple))
+                               throw new ArgumentException ("rest", "The last element of an eight element tuple must be a Tuple.");
                }
        }
 
+       interface ITuple
+       {
+               string ToString ();
+       }
+
        /* The rest is generated by the script at the bottom */
 
        [Serializable]
-       public class Tuple<T1> : IStructuralEquatable, IStructuralComparable, IComparable
+       public class Tuple<T1> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
 
@@ -87,7 +84,7 @@ namespace System
                        var t = other as Tuple<T1>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        return comparer.Compare (item1, t.item1);
@@ -101,10 +98,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1);
                }
@@ -119,14 +114,19 @@ namespace System
                        return comparer.GetHashCode (item1);
                }
 
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}", item1);
+               }
+
                public override string ToString ()
                {
-                       return String.Format ("({0})", item1);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
        [Serializable]
-       public class Tuple<T1, T2> : IStructuralEquatable, IStructuralComparable, IComparable
+       public class Tuple<T1, T2> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
                T2 item2;
@@ -155,7 +155,7 @@ namespace System
                        var t = other as Tuple<T1, T2>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        int res = comparer.Compare (item1, t.item1);
@@ -171,10 +171,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1, T2>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1) &&
                                comparer.Equals (item2, t.item2);
@@ -187,19 +185,25 @@ namespace System
 
                int IStructuralEquatable.GetHashCode (IEqualityComparer comparer)
                {
-                       int h = comparer.GetHashCode (item1);
-                       h = (h << 5) - h + comparer.GetHashCode (item2);
-                       return h;
+                       int h0;
+                       h0 = comparer.GetHashCode (item1);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item2);
+                       return h0;
+               }
+
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}, {1}", item1, item2);
                }
 
                public override string ToString ()
                {
-                       return String.Format ("({0}, {1})", item1, item2);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
        [Serializable]
-       public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable
+       public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
                T2 item2;
@@ -234,7 +238,7 @@ namespace System
                        var t = other as Tuple<T1, T2, T3>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        int res = comparer.Compare (item1, t.item1);
@@ -252,10 +256,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1, T2, T3>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1) &&
                                comparer.Equals (item2, t.item2) &&
@@ -269,20 +271,26 @@ namespace System
 
                int IStructuralEquatable.GetHashCode (IEqualityComparer comparer)
                {
-                       int h = comparer.GetHashCode (item1);
-                       h = (h << 5) - h + comparer.GetHashCode (item2);
-                       h = (h << 5) - h + comparer.GetHashCode (item3);
-                       return h;
+                       int h0;
+                       h0 = comparer.GetHashCode (item1);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item2);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item3);
+                       return h0;
+               }
+
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}, {1}, {2}", item1, item2, item3);
                }
 
                public override string ToString ()
                {
-                       return String.Format ("({0}, {1}, {2})", item1, item2, item3);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
        [Serializable]
-       public class Tuple<T1, T2, T3, T4> : IStructuralEquatable, IStructuralComparable, IComparable
+       public class Tuple<T1, T2, T3, T4> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
                T2 item2;
@@ -323,7 +331,7 @@ namespace System
                        var t = other as Tuple<T1, T2, T3, T4>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        int res = comparer.Compare (item1, t.item1);
@@ -343,10 +351,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1, T2, T3, T4>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1) &&
                                comparer.Equals (item2, t.item2) &&
@@ -361,21 +367,28 @@ namespace System
 
                int IStructuralEquatable.GetHashCode (IEqualityComparer comparer)
                {
-                       int h = comparer.GetHashCode (item1);
-                       h = (h << 5) - h + comparer.GetHashCode (item2);
-                       h = (h << 5) - h + comparer.GetHashCode (item3);
-                       h = (h << 5) - h + comparer.GetHashCode (item4);
-                       return h;
+                       int h0, h1;
+                       h0 = comparer.GetHashCode (item1);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item2);
+                       h1 = comparer.GetHashCode (item3);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item4);
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       return h0;
+               }
+
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}, {1}, {2}, {3}", item1, item2, item3, item4);
                }
 
                public override string ToString ()
                {
-                       return String.Format ("({0}, {1}, {2}, {3})", item1, item2, item3, item4);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
        [Serializable]
-       public class Tuple<T1, T2, T3, T4, T5> : IStructuralEquatable, IStructuralComparable, IComparable
+       public class Tuple<T1, T2, T3, T4, T5> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
                T2 item2;
@@ -422,7 +435,7 @@ namespace System
                        var t = other as Tuple<T1, T2, T3, T4, T5>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        int res = comparer.Compare (item1, t.item1);
@@ -444,10 +457,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1, T2, T3, T4, T5>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1) &&
                                comparer.Equals (item2, t.item2) &&
@@ -463,22 +474,29 @@ namespace System
 
                int IStructuralEquatable.GetHashCode (IEqualityComparer comparer)
                {
-                       int h = comparer.GetHashCode (item1);
-                       h = (h << 5) - h + comparer.GetHashCode (item2);
-                       h = (h << 5) - h + comparer.GetHashCode (item3);
-                       h = (h << 5) - h + comparer.GetHashCode (item4);
-                       h = (h << 5) - h + comparer.GetHashCode (item5);
-                       return h;
+                       int h0, h1;
+                       h0 = comparer.GetHashCode (item1);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item2);
+                       h1 = comparer.GetHashCode (item3);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item4);
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item5);
+                       return h0;
+               }
+
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}, {1}, {2}, {3}, {4}", item1, item2, item3, item4, item5);
                }
 
                public override string ToString ()
                {
-                       return String.Format ("({0}, {1}, {2}, {3}, {4})", item1, item2, item3, item4, item5);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
        [Serializable]
-       public class Tuple<T1, T2, T3, T4, T5, T6> : IStructuralEquatable, IStructuralComparable, IComparable
+       public class Tuple<T1, T2, T3, T4, T5, T6> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
                T2 item2;
@@ -531,7 +549,7 @@ namespace System
                        var t = other as Tuple<T1, T2, T3, T4, T5, T6>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        int res = comparer.Compare (item1, t.item1);
@@ -555,10 +573,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1, T2, T3, T4, T5, T6>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1) &&
                                comparer.Equals (item2, t.item2) &&
@@ -575,23 +591,31 @@ namespace System
 
                int IStructuralEquatable.GetHashCode (IEqualityComparer comparer)
                {
-                       int h = comparer.GetHashCode (item1);
-                       h = (h << 5) - h + comparer.GetHashCode (item2);
-                       h = (h << 5) - h + comparer.GetHashCode (item3);
-                       h = (h << 5) - h + comparer.GetHashCode (item4);
-                       h = (h << 5) - h + comparer.GetHashCode (item5);
-                       h = (h << 5) - h + comparer.GetHashCode (item6);
-                       return h;
+                       int h0, h1;
+                       h0 = comparer.GetHashCode (item1);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item2);
+                       h1 = comparer.GetHashCode (item3);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item4);
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       h1 = comparer.GetHashCode (item5);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item6);
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       return h0;
+               }
+
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}, {1}, {2}, {3}, {4}, {5}", item1, item2, item3, item4, item5, item6);
                }
 
                public override string ToString ()
                {
-                       return String.Format ("({0}, {1}, {2}, {3}, {4}, {5})", item1, item2, item3, item4, item5, item6);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
        [Serializable]
-       public class Tuple<T1, T2, T3, T4, T5, T6, T7> : IStructuralEquatable, IStructuralComparable, IComparable
+       public class Tuple<T1, T2, T3, T4, T5, T6, T7> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
                T2 item2;
@@ -650,7 +674,7 @@ namespace System
                        var t = other as Tuple<T1, T2, T3, T4, T5, T6, T7>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        int res = comparer.Compare (item1, t.item1);
@@ -676,10 +700,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1, T2, T3, T4, T5, T6, T7>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1) &&
                                comparer.Equals (item2, t.item2) &&
@@ -697,24 +719,32 @@ namespace System
 
                int IStructuralEquatable.GetHashCode (IEqualityComparer comparer)
                {
-                       int h = comparer.GetHashCode (item1);
-                       h = (h << 5) - h + comparer.GetHashCode (item2);
-                       h = (h << 5) - h + comparer.GetHashCode (item3);
-                       h = (h << 5) - h + comparer.GetHashCode (item4);
-                       h = (h << 5) - h + comparer.GetHashCode (item5);
-                       h = (h << 5) - h + comparer.GetHashCode (item6);
-                       h = (h << 5) - h + comparer.GetHashCode (item7);
-                       return h;
+                       int h0, h1;
+                       h0 = comparer.GetHashCode (item1);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item2);
+                       h1 = comparer.GetHashCode (item3);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item4);
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       h1 = comparer.GetHashCode (item5);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item6);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item7);
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       return h0;
+               }
+
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}, {1}, {2}, {3}, {4}, {5}, {6}", item1, item2, item3, item4, item5, item6, item7);
                }
 
                public override string ToString ()
                {
-                       return String.Format ("({0}, {1}, {2}, {3}, {4}, {5}, {6})", item1, item2, item3, item4, item5, item6, item7);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
        [Serializable]
-       public partial class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> : IStructuralEquatable, IStructuralComparable, IComparable
+       public partial class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        {
                T1 item1;
                T2 item2;
@@ -767,7 +797,7 @@ namespace System
                        var t = other as Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>;
                        if (t == null) {
                                if (other == null) return 1;
-                               throw new ArgumentException ();
+                               throw new ArgumentException ("other");
                        }
 
                        int res = comparer.Compare (item1, t.item1);
@@ -795,10 +825,8 @@ namespace System
                bool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)
                {
                        var t = other as Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>;
-                       if (t == null) {
-                               if (other == null) return false;
-                               throw new ArgumentException ();
-                       }
+                       if (t == null)
+                               return false;
 
                        return comparer.Equals (item1, t.item1) &&
                                comparer.Equals (item2, t.item2) &&
@@ -817,20 +845,29 @@ namespace System
 
                int IStructuralEquatable.GetHashCode (IEqualityComparer comparer)
                {
-                       int h = comparer.GetHashCode (item1);
-                       h = (h << 5) - h + comparer.GetHashCode (item2);
-                       h = (h << 5) - h + comparer.GetHashCode (item3);
-                       h = (h << 5) - h + comparer.GetHashCode (item4);
-                       h = (h << 5) - h + comparer.GetHashCode (item5);
-                       h = (h << 5) - h + comparer.GetHashCode (item6);
-                       h = (h << 5) - h + comparer.GetHashCode (item7);
-                       h = (h << 5) - h + comparer.GetHashCode (rest);
-                       return h;
+                       int h0, h1, h2;
+                       h0 = comparer.GetHashCode (item1);
+                       h0 = (h0 << 5) + h0 ^ comparer.GetHashCode (item2);
+                       h1 = comparer.GetHashCode (item3);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item4);
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       h1 = comparer.GetHashCode (item5);
+                       h1 = (h1 << 5) + h1 ^ comparer.GetHashCode (item6);
+                       h2 = comparer.GetHashCode (item7);
+                       h2 = (h2 << 5) + h2 ^ comparer.GetHashCode (rest);
+                       h1 = (h1 << 5) + h1 ^ h2;
+                       h0 = (h0 << 5) + h0 ^ h1;
+                       return h0;
+               }
+
+               string ITuple.ToString ()
+               {
+                       return String.Format ("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", item1, item2, item3, item4, item5, item6, item7, ((ITuple)rest).ToString ());
                }
 
                public override string ToString ()
                {
-                       return String.Format ("({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7})", item1, item2, item3, item4, item5, item6, item7, rest);
+                       return "(" + ((ITuple) this).ToString () + ")";
                }
        }
 
@@ -856,11 +893,11 @@ public class TupleGen
                        Console.WriteLine ("\t[Serializable]");
                        Console.Write ("\tpublic {0}class ", arity < 8 ? null : "partial ");
                        Console.Write (type_name);
-                       Console.WriteLine (" : IStructuralEquatable, IStructuralComparable, IComparable");
+                       Console.WriteLine (" : IStructuralEquatable, IStructuralComparable, IComparable, ITuple");
                        Console.WriteLine ("\t{");
                        for (int i = 1; i <= arity; ++i)
                                Console.WriteLine ("\t\t{0} {1};", GetItemTypeName (i), GetItemName (i));
-                               
+
                        if (arity < 8) {
                                Console.WriteLine ();
                                Console.Write ("\t\tpublic Tuple (");
@@ -890,17 +927,17 @@ public class TupleGen
                        Console.WriteLine ("\t\t{");
                        Console.WriteLine ("\t\t\treturn ((IStructuralComparable) this).CompareTo (obj, Comparer<object>.Default);");
                        Console.WriteLine ("\t\t}");
-                       
+
                        Console.WriteLine ();
                        Console.WriteLine ("\t\tint IStructuralComparable.CompareTo (object other, IComparer comparer)");
                        Console.WriteLine ("\t\t{");
                        Console.WriteLine ("\t\t\tvar t = other as {0};", type_name);
                        Console.WriteLine ("\t\t\tif (t == null) {");
                        Console.WriteLine ("\t\t\t\tif (other == null) return 1;");
-                       Console.WriteLine ("\t\t\t\tthrow new ArgumentException ();");
+                       Console.WriteLine ("\t\t\t\tthrow new ArgumentException (\"other\");");
                        Console.WriteLine ("\t\t\t}");
                        Console.WriteLine ();
-                       
+
                        for (int i = 1; i < arity; ++i) {
                                Console.Write ("\t\t\t");
                                if (i == 1)
@@ -910,25 +947,23 @@ public class TupleGen
                                Console.WriteLine ("\t\t\tif (res != 0) return res;");
                        }
                        Console.WriteLine ("\t\t\treturn comparer.Compare ({0}, t.{0});", GetItemName (arity));
-                       Console.WriteLine ("\t\t}");                    
-                       
+                       Console.WriteLine ("\t\t}");
+
                        Console.WriteLine ();
                        Console.WriteLine ("\t\tpublic override bool Equals (object obj)");
                        Console.WriteLine ("\t\t{");
                        Console.WriteLine ("\t\t\treturn ((IStructuralEquatable) this).Equals (obj, EqualityComparer<object>.Default);");
                        Console.WriteLine ("\t\t}");
-                       
+
                        Console.WriteLine ();
                        Console.WriteLine ("\t\tbool IStructuralEquatable.Equals (object other, IEqualityComparer comparer)");
                        Console.WriteLine ("\t\t{");
                        Console.WriteLine ("\t\t\tvar t = other as {0};", type_name);
-                       Console.WriteLine ("\t\t\tif (t == null) {");
-                       Console.WriteLine ("\t\t\t\tif (other == null) return false;");
-                       Console.WriteLine ("\t\t\t\tthrow new ArgumentException ();");
-                       Console.WriteLine ("\t\t\t}");
+                       Console.WriteLine ("\t\t\tif (t == null)");
+                       Console.WriteLine ("\t\t\t\treturn false;");
                        Console.WriteLine ();
                        Console.Write ("\t\t\treturn");
-                       
+
                        for (int i = 1; i <= arity; ++i) {
                                if (i == 1)
                                        Console.Write (" ");
@@ -942,49 +977,91 @@ public class TupleGen
                                        Console.WriteLine (";");
                        }
                        Console.WriteLine ("\t\t}");
-                       
+
                        Console.WriteLine ();
                        Console.WriteLine ("\t\tpublic override int GetHashCode ()");
                        Console.WriteLine ("\t\t{");
                        Console.WriteLine ("\t\t\treturn ((IStructuralEquatable) this).GetHashCode (EqualityComparer<object>.Default);");
                        Console.WriteLine ("\t\t}");
-                       
+
                        Console.WriteLine ();
                        Console.WriteLine ("\t\tint IStructuralEquatable.GetHashCode (IEqualityComparer comparer)");
                        Console.WriteLine ("\t\t{");
                        if (arity == 1) {
                                Console.WriteLine ("\t\t\treturn comparer.GetHashCode ({0});", GetItemName (arity));
                        } else {
-                               Console.WriteLine ("\t\t\tint h = comparer.GetHashCode ({0});", GetItemName (1));
-                               for (int i = 2; i <= arity; ++i)
-                                       Console.WriteLine ("\t\t\th = (h << 5) - h + comparer.GetHashCode ({0});", GetItemName (i));
-                               Console.WriteLine ("\t\t\treturn h;");
+                               int varnum = IntLog2 (arity);
+                               Console.Write ("\t\t\tint h0");
+                               for (int i = 1; i < varnum; ++i)
+                                       Console.Write (", h{0}", i);
+                               Console.WriteLine (";");
+
+                               WriteHash (0, 1, arity);
+
+                               Console.WriteLine ("\t\t\treturn h0;");
                        }
 
                        Console.WriteLine ("\t\t}");
 
                        Console.WriteLine ();
-                       Console.WriteLine ("\t\tpublic override string ToString ()");
+                       Console.WriteLine ("\t\tstring ITuple.ToString ()");
                        Console.WriteLine ("\t\t{");
-                       Console.Write ("\t\t\treturn String.Format (\"(");
+                       Console.Write ("\t\t\treturn String.Format (\"");
                        for (int i = 1; i <= arity; ++i) {
                                Console.Write ("{" + (i - 1) + "}");
                                if (i < arity)
                                        Console.Write (", ");
                        }
-                       Console.Write (")\", ");
+                       Console.Write ("\", ");
                        for (int i = 1; i <= arity; ++i) {
-                               Console.Write (GetItemName (i));
+                               var item_name = GetItemName (i);
+                               Console.Write (i == 8 ? "((ITuple){0}).ToString ()" : "{0}", item_name);
                                if (i < arity)
                                        Console.Write (", ");
                        }
                        Console.WriteLine (");");
                        Console.WriteLine ("\t\t}");
 
+                       Console.WriteLine ();
+                       Console.WriteLine ("\t\tpublic override string ToString ()");
+                       Console.WriteLine ("\t\t{");
+                       Console.WriteLine ("\t\t\treturn \"(\" + ((ITuple) this).ToString () + \")\";");
+                       Console.WriteLine ("\t\t}");
+
                        Console.WriteLine ("\t}\n");
                }
        }
 
+       static int IntLog2 (int n)
+       {
+               int r = -1;
+
+               while (n != 0) {
+                       n >>= 1;
+                       r++;
+               }
+
+               return r;
+       }
+
+       static void WriteHash (int destVar, int start, int count)
+       {
+               if (count == 1) {
+                       Console.WriteLine ("\t\t\th{0} = comparer.GetHashCode ({1});", destVar, GetItemName (start));
+               } else {
+                       int subCount = 1 << IntLog2 (count - 1);
+                       WriteHash (destVar, start, subCount);
+                       start += subCount;
+                       count -= subCount;
+                       if (count == 1) {
+                               Console.WriteLine ("\t\t\th{0} = (h{0} << 5) + h{0} ^ comparer.GetHashCode ({1});", destVar, GetItemName (start));
+                       } else {
+                               WriteHash (destVar + 1, start, count);
+                               Console.WriteLine ("\t\t\th{0} = (h{0} << 5) + h{0} ^ h{1};", destVar, destVar + 1);
+                       }
+               }
+       }
+
        static string GetTypeName (int arity)
        {
                StringBuilder sb = new StringBuilder ();
@@ -995,19 +1072,20 @@ public class TupleGen
                                sb.Append (", ");
                }
                sb.Append (">");
-               
+
                return sb.ToString ();
        }
-       
+
        static string GetItemName (int arity)
        {
                return arity < 8 ? "item" + arity.ToString () : "rest";
        }
-       
+
        static string GetItemTypeName (int arity)
        {
                return arity < 8 ? "T" + arity.ToString () : "TRest";
        }
 }
 
+
 #endif