1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections;
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.Runtime.InteropServices;
9 using System.Runtime.CompilerServices;
10 using HashHelpers = System.Numerics.Hashing.HashHelpers;
11 
12 namespace System
13 {
14     /// <summary>
15     /// Helper so we can call some tuple methods recursively without knowing the underlying types.
16     /// </summary>
17     internal interface IValueTupleInternal : ITuple
18     {
GetHashCode(IEqualityComparer comparer)19         int GetHashCode(IEqualityComparer comparer);
ToStringEnd()20         string ToStringEnd();
21     }
22 
23     /// <summary>
24     /// The ValueTuple types (from arity 0 to 8) comprise the runtime implementation that underlies tuples in C# and struct tuples in F#.
25     /// Aside from created via language syntax, they are most easily created via the ValueTuple.Create factory methods.
26     /// The System.ValueTuple types differ from the System.Tuple types in that:
27     /// - they are structs rather than classes,
28     /// - they are mutable rather than readonly, and
29     /// - their members (such as Item1, Item2, etc) are fields rather than properties.
30     /// </summary>
31     [Serializable]
32 #if !MONO
33     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
34 #endif
35     public struct ValueTuple
36         : IEquatable<ValueTuple>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple>, IValueTupleInternal, ITuple
37     {
38         /// <summary>
39         /// Returns a value that indicates whether the current <see cref="ValueTuple"/> instance is equal to a specified object.
40         /// </summary>
41         /// <param name="obj">The object to compare with this instance.</param>
42         /// <returns><see langword="true"/> if <paramref name="obj"/> is a <see cref="ValueTuple"/>.</returns>
EqualsSystem.ValueTuple43         public override bool Equals(object obj)
44         {
45             return obj is ValueTuple;
46         }
47 
48         /// <summary>Returns a value indicating whether this instance is equal to a specified value.</summary>
49         /// <param name="other">An instance to compare to this instance.</param>
50         /// <returns>true if <paramref name="other"/> has the same value as this instance; otherwise, false.</returns>
EqualsSystem.ValueTuple51         public bool Equals(ValueTuple other)
52         {
53             return true;
54         }
55 
IStructuralEquatable.EqualsSystem.ValueTuple56         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
57         {
58             return other is ValueTuple;
59         }
60 
IComparable.CompareToSystem.ValueTuple61         int IComparable.CompareTo(object other)
62         {
63             if (other == null) return 1;
64 
65             if (!(other is ValueTuple))
66             {
67                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
68             }
69 
70             return 0;
71         }
72 
73         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
74         /// <param name="other">An instance to compare.</param>
75         /// <returns>
76         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
77         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
78         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
79         /// than <paramref name="other"/>.
80         /// </returns>
CompareToSystem.ValueTuple81         public int CompareTo(ValueTuple other)
82         {
83             return 0;
84         }
85 
IStructuralComparable.CompareToSystem.ValueTuple86         int IStructuralComparable.CompareTo(object other, IComparer comparer)
87         {
88             if (other == null) return 1;
89 
90             if (!(other is ValueTuple))
91             {
92                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
93             }
94 
95             return 0;
96         }
97 
98         /// <summary>Returns the hash code for this instance.</summary>
99         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple100         public override int GetHashCode()
101         {
102             return 0;
103         }
104 
IStructuralEquatable.GetHashCodeSystem.ValueTuple105         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
106         {
107             return 0;
108         }
109 
IValueTupleInternal.GetHashCodeSystem.ValueTuple110         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
111         {
112             return 0;
113         }
114 
115         /// <summary>
116         /// Returns a string that represents the value of this <see cref="ValueTuple"/> instance.
117         /// </summary>
118         /// <returns>The string representation of this <see cref="ValueTuple"/> instance.</returns>
119         /// <remarks>
120         /// The string returned by this method takes the form <c>()</c>.
121         /// </remarks>
ToStringSystem.ValueTuple122         public override string ToString()
123         {
124             return "()";
125         }
126 
IValueTupleInternal.ToStringEndSystem.ValueTuple127         string IValueTupleInternal.ToStringEnd()
128         {
129             return ")";
130         }
131 
132         /// <summary>
133         /// The number of positions in this data structure.
134         /// </summary>
135         int ITuple.Length => 0;
136 
137         /// <summary>
138         /// Get the element at position <param name="index"/>.
139         /// </summary>
140         object ITuple.this[int index]
141         {
142             get
143             {
144                 throw new IndexOutOfRangeException();
145             }
146         }
147 
148         /// <summary>Creates a new struct 0-tuple.</summary>
149         /// <returns>A 0-tuple.</returns>
CreateSystem.ValueTuple150         public static ValueTuple Create() =>
151             new ValueTuple();
152 
153         /// <summary>Creates a new struct 1-tuple, or singleton.</summary>
154         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
155         /// <param name="item1">The value of the first component of the tuple.</param>
156         /// <returns>A 1-tuple (singleton) whose value is (item1).</returns>
157         public static ValueTuple<T1> Create<T1>(T1 item1) =>
158             new ValueTuple<T1>(item1);
159 
160         /// <summary>Creates a new struct 2-tuple, or pair.</summary>
161         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
162         /// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
163         /// <param name="item1">The value of the first component of the tuple.</param>
164         /// <param name="item2">The value of the second component of the tuple.</param>
165         /// <returns>A 2-tuple (pair) whose value is (item1, item2).</returns>
CreateSystem.ValueTuple166         public static ValueTuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) =>
167             new ValueTuple<T1, T2>(item1, item2);
168 
169         /// <summary>Creates a new struct 3-tuple, or triple.</summary>
170         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
171         /// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
172         /// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
173         /// <param name="item1">The value of the first component of the tuple.</param>
174         /// <param name="item2">The value of the second component of the tuple.</param>
175         /// <param name="item3">The value of the third component of the tuple.</param>
176         /// <returns>A 3-tuple (triple) whose value is (item1, item2, item3).</returns>
CreateSystem.ValueTuple177         public static ValueTuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3) =>
178             new ValueTuple<T1, T2, T3>(item1, item2, item3);
179 
180         /// <summary>Creates a new struct 4-tuple, or quadruple.</summary>
181         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
182         /// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
183         /// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
184         /// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
185         /// <param name="item1">The value of the first component of the tuple.</param>
186         /// <param name="item2">The value of the second component of the tuple.</param>
187         /// <param name="item3">The value of the third component of the tuple.</param>
188         /// <param name="item4">The value of the fourth component of the tuple.</param>
189         /// <returns>A 4-tuple (quadruple) whose value is (item1, item2, item3, item4).</returns>
CreateSystem.ValueTuple190         public static ValueTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4) =>
191             new ValueTuple<T1, T2, T3, T4>(item1, item2, item3, item4);
192 
193         /// <summary>Creates a new struct 5-tuple, or quintuple.</summary>
194         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
195         /// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
196         /// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
197         /// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
198         /// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
199         /// <param name="item1">The value of the first component of the tuple.</param>
200         /// <param name="item2">The value of the second component of the tuple.</param>
201         /// <param name="item3">The value of the third component of the tuple.</param>
202         /// <param name="item4">The value of the fourth component of the tuple.</param>
203         /// <param name="item5">The value of the fifth component of the tuple.</param>
204         /// <returns>A 5-tuple (quintuple) whose value is (item1, item2, item3, item4, item5).</returns>
CreateSystem.ValueTuple205         public static ValueTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) =>
206             new ValueTuple<T1, T2, T3, T4, T5>(item1, item2, item3, item4, item5);
207 
208         /// <summary>Creates a new struct 6-tuple, or sextuple.</summary>
209         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
210         /// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
211         /// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
212         /// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
213         /// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
214         /// <typeparam name="T6">The type of the sixth component of the tuple.</typeparam>
215         /// <param name="item1">The value of the first component of the tuple.</param>
216         /// <param name="item2">The value of the second component of the tuple.</param>
217         /// <param name="item3">The value of the third component of the tuple.</param>
218         /// <param name="item4">The value of the fourth component of the tuple.</param>
219         /// <param name="item5">The value of the fifth component of the tuple.</param>
220         /// <param name="item6">The value of the sixth component of the tuple.</param>
221         /// <returns>A 6-tuple (sextuple) whose value is (item1, item2, item3, item4, item5, item6).</returns>
CreateSystem.ValueTuple222         public static ValueTuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) =>
223             new ValueTuple<T1, T2, T3, T4, T5, T6>(item1, item2, item3, item4, item5, item6);
224 
225         /// <summary>Creates a new struct 7-tuple, or septuple.</summary>
226         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
227         /// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
228         /// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
229         /// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
230         /// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
231         /// <typeparam name="T6">The type of the sixth component of the tuple.</typeparam>
232         /// <typeparam name="T7">The type of the seventh component of the tuple.</typeparam>
233         /// <param name="item1">The value of the first component of the tuple.</param>
234         /// <param name="item2">The value of the second component of the tuple.</param>
235         /// <param name="item3">The value of the third component of the tuple.</param>
236         /// <param name="item4">The value of the fourth component of the tuple.</param>
237         /// <param name="item5">The value of the fifth component of the tuple.</param>
238         /// <param name="item6">The value of the sixth component of the tuple.</param>
239         /// <param name="item7">The value of the seventh component of the tuple.</param>
240         /// <returns>A 7-tuple (septuple) whose value is (item1, item2, item3, item4, item5, item6, item7).</returns>
CreateSystem.ValueTuple241         public static ValueTuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) =>
242             new ValueTuple<T1, T2, T3, T4, T5, T6, T7>(item1, item2, item3, item4, item5, item6, item7);
243 
244         /// <summary>Creates a new struct 8-tuple, or octuple.</summary>
245         /// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
246         /// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
247         /// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
248         /// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
249         /// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
250         /// <typeparam name="T6">The type of the sixth component of the tuple.</typeparam>
251         /// <typeparam name="T7">The type of the seventh component of the tuple.</typeparam>
252         /// <typeparam name="T8">The type of the eighth component of the tuple.</typeparam>
253         /// <param name="item1">The value of the first component of the tuple.</param>
254         /// <param name="item2">The value of the second component of the tuple.</param>
255         /// <param name="item3">The value of the third component of the tuple.</param>
256         /// <param name="item4">The value of the fourth component of the tuple.</param>
257         /// <param name="item5">The value of the fifth component of the tuple.</param>
258         /// <param name="item6">The value of the sixth component of the tuple.</param>
259         /// <param name="item7">The value of the seventh component of the tuple.</param>
260         /// <param name="item8">The value of the eighth component of the tuple.</param>
261         /// <returns>An 8-tuple (octuple) whose value is (item1, item2, item3, item4, item5, item6, item7, item8).</returns>
CreateSystem.ValueTuple262         public static ValueTuple<T1, T2, T3, T4, T5, T6, T7, ValueTuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) =>
263             new ValueTuple<T1, T2, T3, T4, T5, T6, T7, ValueTuple<T8>>(item1, item2, item3, item4, item5, item6, item7, ValueTuple.Create(item8));
264 
CombineHashCodesSystem.ValueTuple265         internal static int CombineHashCodes(int h1, int h2)
266         {
267             return HashHelpers.Combine(HashHelpers.Combine(HashHelpers.RandomSeed, h1), h2);
268         }
269 
CombineHashCodesSystem.ValueTuple270         internal static int CombineHashCodes(int h1, int h2, int h3)
271         {
272             return HashHelpers.Combine(CombineHashCodes(h1, h2), h3);
273         }
274 
CombineHashCodesSystem.ValueTuple275         internal static int CombineHashCodes(int h1, int h2, int h3, int h4)
276         {
277             return HashHelpers.Combine(CombineHashCodes(h1, h2, h3), h4);
278         }
279 
CombineHashCodesSystem.ValueTuple280         internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5)
281         {
282             return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4), h5);
283         }
284 
CombineHashCodesSystem.ValueTuple285         internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6)
286         {
287             return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5), h6);
288         }
289 
CombineHashCodesSystem.ValueTuple290         internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7)
291         {
292             return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5, h6), h7);
293         }
294 
CombineHashCodesSystem.ValueTuple295         internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8)
296         {
297             return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5, h6, h7), h8);
298         }
299     }
300 
301     /// <summary>Represents a 1-tuple, or singleton, as a value type.</summary>
302     /// <typeparam name="T1">The type of the tuple's only component.</typeparam>
303     [Serializable]
304 #if !MONO
305     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
306 #endif
307     public struct ValueTuple<T1>
308         : IEquatable<ValueTuple<T1>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1>>, IValueTupleInternal, ITuple
309     {
310         /// <summary>
311         /// The current <see cref="ValueTuple{T1}"/> instance's first component.
312         /// </summary>
313         public T1 Item1;
314 
315         /// <summary>
316         /// Initializes a new instance of the <see cref="ValueTuple{T1}"/> value type.
317         /// </summary>
318         /// <param name="item1">The value of the tuple's first component.</param>
ValueTupleSystem.ValueTuple319         public ValueTuple(T1 item1)
320         {
321             Item1 = item1;
322         }
323 
324         /// <summary>
325         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1}"/> instance is equal to a specified object.
326         /// </summary>
327         /// <param name="obj">The object to compare with this instance.</param>
328         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
329         /// <remarks>
330         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
331         /// <list type="bullet">
332         ///     <item><description>It is a <see cref="ValueTuple{T1}"/> value type.</description></item>
333         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
334         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
335         /// </list>
336         /// </remarks>
EqualsSystem.ValueTuple337         public override bool Equals(object obj)
338         {
339             return obj is ValueTuple<T1> && Equals((ValueTuple<T1>)obj);
340         }
341 
342         /// <summary>
343         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1}"/>
344         /// instance is equal to a specified <see cref="ValueTuple{T1}"/>.
345         /// </summary>
346         /// <param name="other">The tuple to compare with this instance.</param>
347         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
348         /// <remarks>
349         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its field
350         /// is equal to that of the current instance, using the default comparer for that field's type.
351         /// </remarks>
EqualsSystem.ValueTuple352         public bool Equals(ValueTuple<T1> other)
353         {
354             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1);
355         }
356 
IStructuralEquatable.EqualsSystem.ValueTuple357         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
358         {
359             if (other == null || !(other is ValueTuple<T1>)) return false;
360 
361             var objTuple = (ValueTuple<T1>)other;
362 
363             return comparer.Equals(Item1, objTuple.Item1);
364         }
365 
IComparable.CompareToSystem.ValueTuple366         int IComparable.CompareTo(object other)
367         {
368             if (other == null) return 1;
369 
370             if (!(other is ValueTuple<T1>))
371             {
372                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
373             }
374 
375             var objTuple = (ValueTuple<T1>)other;
376 
377             return Comparer<T1>.Default.Compare(Item1, objTuple.Item1);
378         }
379 
380         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
381         /// <param name="other">An instance to compare.</param>
382         /// <returns>
383         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
384         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
385         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
386         /// than <paramref name="other"/>.
387         /// </returns>
CompareToSystem.ValueTuple388         public int CompareTo(ValueTuple<T1> other)
389         {
390             return Comparer<T1>.Default.Compare(Item1, other.Item1);
391         }
392 
IStructuralComparable.CompareToSystem.ValueTuple393         int IStructuralComparable.CompareTo(object other, IComparer comparer)
394         {
395             if (other == null) return 1;
396 
397             if (!(other is ValueTuple<T1>))
398             {
399                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
400             }
401 
402             var objTuple = (ValueTuple<T1>)other;
403 
404             return comparer.Compare(Item1, objTuple.Item1);
405         }
406 
407         /// <summary>
408         /// Returns the hash code for the current <see cref="ValueTuple{T1}"/> instance.
409         /// </summary>
410         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple411         public override int GetHashCode()
412         {
413             return Item1?.GetHashCode() ?? 0;
414         }
415 
IStructuralEquatable.GetHashCodeSystem.ValueTuple416         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
417         {
418             return comparer.GetHashCode(Item1);
419         }
420 
IValueTupleInternal.GetHashCodeSystem.ValueTuple421         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
422         {
423             return comparer.GetHashCode(Item1);
424         }
425 
426         /// <summary>
427         /// Returns a string that represents the value of this <see cref="ValueTuple{T1}"/> instance.
428         /// </summary>
429         /// <returns>The string representation of this <see cref="ValueTuple{T1}"/> instance.</returns>
430         /// <remarks>
431         /// The string returned by this method takes the form <c>(Item1)</c>,
432         /// where <c>Item1</c> represents the value of <see cref="Item1"/>. If the field is <see langword="null"/>,
433         /// it is represented as <see cref="string.Empty"/>.
434         /// </remarks>
ToStringSystem.ValueTuple435         public override string ToString()
436         {
437             return "(" + Item1?.ToString() + ")";
438         }
439 
IValueTupleInternal.ToStringEndSystem.ValueTuple440         string IValueTupleInternal.ToStringEnd()
441         {
442             return Item1?.ToString() + ")";
443         }
444 
445         /// <summary>
446         /// The number of positions in this data structure.
447         /// </summary>
448         int ITuple.Length => 1;
449 
450         /// <summary>
451         /// Get the element at position <param name="index"/>.
452         /// </summary>
453         object ITuple.this[int index]
454         {
455             get
456             {
457                 if (index != 0)
458                 {
459                     throw new IndexOutOfRangeException();
460                 }
461                 return Item1;
462             }
463         }
464     }
465 
466     /// <summary>
467     /// Represents a 2-tuple, or pair, as a value type.
468     /// </summary>
469     /// <typeparam name="T1">The type of the tuple's first component.</typeparam>
470     /// <typeparam name="T2">The type of the tuple's second component.</typeparam>
471     [Serializable]
472     [StructLayout(LayoutKind.Auto)]
473 #if !MONO
474     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
475 #endif
476     public struct ValueTuple<T1, T2>
477         : IEquatable<ValueTuple<T1, T2>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2>>, IValueTupleInternal, ITuple
478     {
479         /// <summary>
480         /// The current <see cref="ValueTuple{T1, T2}"/> instance's first component.
481         /// </summary>
482         public T1 Item1;
483 
484         /// <summary>
485         /// The current <see cref="ValueTuple{T1, T2}"/> instance's first component.
486         /// </summary>
487         public T2 Item2;
488 
489         /// <summary>
490         /// Initializes a new instance of the <see cref="ValueTuple{T1, T2}"/> value type.
491         /// </summary>
492         /// <param name="item1">The value of the tuple's first component.</param>
493         /// <param name="item2">The value of the tuple's second component.</param>
ValueTupleSystem.ValueTuple494         public ValueTuple(T1 item1, T2 item2)
495         {
496             Item1 = item1;
497             Item2 = item2;
498         }
499 
500         /// <summary>
501         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2}"/> instance is equal to a specified object.
502         /// </summary>
503         /// <param name="obj">The object to compare with this instance.</param>
504         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
505         ///
506         /// <remarks>
507         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
508         /// <list type="bullet">
509         ///     <item><description>It is a <see cref="ValueTuple{T1, T2}"/> value type.</description></item>
510         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
511         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
512         /// </list>
513         /// </remarks>
EqualsSystem.ValueTuple514         public override bool Equals(object obj)
515         {
516             return obj is ValueTuple<T1, T2> && Equals((ValueTuple<T1, T2>)obj);
517         }
518 
519         /// <summary>
520         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2}"/> instance is equal to a specified <see cref="ValueTuple{T1, T2}"/>.
521         /// </summary>
522         /// <param name="other">The tuple to compare with this instance.</param>
523         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
524         /// <remarks>
525         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
526         /// are equal to that of the current instance, using the default comparer for that field's type.
527         /// </remarks>
EqualsSystem.ValueTuple528         public bool Equals(ValueTuple<T1, T2> other)
529         {
530             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
531                 && EqualityComparer<T2>.Default.Equals(Item2, other.Item2);
532         }
533 
534         /// <summary>
535         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2}"/> instance is equal to a specified object based on a specified comparison method.
536         /// </summary>
537         /// <param name="other">The object to compare with this instance.</param>
538         /// <param name="comparer">An object that defines the method to use to evaluate whether the two objects are equal.</param>
539         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
540         ///
541         /// <remarks>
542         /// This member is an explicit interface member implementation. It can be used only when the
543         ///  <see cref="ValueTuple{T1, T2}"/> instance is cast to an <see cref="IStructuralEquatable"/> interface.
544         ///
545         /// The <see cref="IEqualityComparer.Equals"/> implementation is called only if <c>other</c> is not <see langword="null"/>,
546         ///  and if it can be successfully cast (in C#) or converted (in Visual Basic) to a <see cref="ValueTuple{T1, T2}"/>
547         ///  whose components are of the same types as those of the current instance. The IStructuralEquatable.Equals(Object, IEqualityComparer) method
548         ///  first passes the <see cref="Item1"/> values of the <see cref="ValueTuple{T1, T2}"/> objects to be compared to the
549         ///  <see cref="IEqualityComparer.Equals"/> implementation. If this method call returns <see langword="true"/>, the method is
550         ///  called again and passed the <see cref="Item2"/> values of the two <see cref="ValueTuple{T1, T2}"/> instances.
551         /// </remarks>
IStructuralEquatable.EqualsSystem.ValueTuple552         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
553         {
554             if (other == null || !(other is ValueTuple<T1, T2>)) return false;
555 
556             var objTuple = (ValueTuple<T1, T2>)other;
557 
558             return comparer.Equals(Item1, objTuple.Item1)
559                 && comparer.Equals(Item2, objTuple.Item2);
560         }
561 
IComparable.CompareToSystem.ValueTuple562         int IComparable.CompareTo(object other)
563         {
564             if (other == null) return 1;
565 
566             if (!(other is ValueTuple<T1, T2>))
567             {
568                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
569             }
570 
571             return CompareTo((ValueTuple<T1, T2>)other);
572         }
573 
574         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
575         /// <param name="other">An instance to compare.</param>
576         /// <returns>
577         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
578         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
579         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
580         /// than <paramref name="other"/>.
581         /// </returns>
CompareToSystem.ValueTuple582         public int CompareTo(ValueTuple<T1, T2> other)
583         {
584             int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
585             if (c != 0) return c;
586 
587             return Comparer<T2>.Default.Compare(Item2, other.Item2);
588         }
589 
IStructuralComparable.CompareToSystem.ValueTuple590         int IStructuralComparable.CompareTo(object other, IComparer comparer)
591         {
592             if (other == null) return 1;
593 
594             if (!(other is ValueTuple<T1, T2>))
595             {
596                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
597             }
598 
599             var objTuple = (ValueTuple<T1, T2>)other;
600 
601             int c = comparer.Compare(Item1, objTuple.Item1);
602             if (c != 0) return c;
603 
604             return comparer.Compare(Item2, objTuple.Item2);
605         }
606 
607         /// <summary>
608         /// Returns the hash code for the current <see cref="ValueTuple{T1, T2}"/> instance.
609         /// </summary>
610         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple611         public override int GetHashCode()
612         {
613             return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
614                                                Item2?.GetHashCode() ?? 0);
615         }
616 
IStructuralEquatable.GetHashCodeSystem.ValueTuple617         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
618         {
619             return GetHashCodeCore(comparer);
620         }
621 
GetHashCodeCoreSystem.ValueTuple622         private int GetHashCodeCore(IEqualityComparer comparer)
623         {
624             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
625                                                comparer.GetHashCode(Item2));
626         }
627 
IValueTupleInternal.GetHashCodeSystem.ValueTuple628         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
629         {
630             return GetHashCodeCore(comparer);
631         }
632 
633         /// <summary>
634         /// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2}"/> instance.
635         /// </summary>
636         /// <returns>The string representation of this <see cref="ValueTuple{T1, T2}"/> instance.</returns>
637         /// <remarks>
638         /// The string returned by this method takes the form <c>(Item1, Item2)</c>,
639         /// where <c>Item1</c> and <c>Item2</c> represent the values of the <see cref="Item1"/>
640         /// and <see cref="Item2"/> fields. If either field value is <see langword="null"/>,
641         /// it is represented as <see cref="String.Empty"/>.
642         /// </remarks>
ToStringSystem.ValueTuple643         public override string ToString()
644         {
645             return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ")";
646         }
647 
IValueTupleInternal.ToStringEndSystem.ValueTuple648         string IValueTupleInternal.ToStringEnd()
649         {
650             return Item1?.ToString() + ", " + Item2?.ToString() + ")";
651         }
652 
653         /// <summary>
654         /// The number of positions in this data structure.
655         /// </summary>
656         int ITuple.Length => 2;
657 
658         /// <summary>
659         /// Get the element at position <param name="index"/>.
660         /// </summary>
661         object ITuple.this[int index]
662         {
663             get
664             {
665                 switch (index)
666                 {
667                     case 0:
668                         return Item1;
669                     case 1:
670                         return Item2;
671                     default:
672                         throw new IndexOutOfRangeException();
673                 }
674             }
675         }
676     }
677 
678     /// <summary>
679     /// Represents a 3-tuple, or triple, as a value type.
680     /// </summary>
681     /// <typeparam name="T1">The type of the tuple's first component.</typeparam>
682     /// <typeparam name="T2">The type of the tuple's second component.</typeparam>
683     /// <typeparam name="T3">The type of the tuple's third component.</typeparam>
684     [Serializable]
685     [StructLayout(LayoutKind.Auto)]
686 #if !MONO
687     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
688 #endif
689     public struct ValueTuple<T1, T2, T3>
690         : IEquatable<ValueTuple<T1, T2, T3>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3>>, IValueTupleInternal, ITuple
691     {
692         /// <summary>
693         /// The current <see cref="ValueTuple{T1, T2, T3}"/> instance's first component.
694         /// </summary>
695         public T1 Item1;
696         /// <summary>
697         /// The current <see cref="ValueTuple{T1, T2, T3}"/> instance's second component.
698         /// </summary>
699         public T2 Item2;
700         /// <summary>
701         /// The current <see cref="ValueTuple{T1, T2, T3}"/> instance's third component.
702         /// </summary>
703         public T3 Item3;
704 
705         /// <summary>
706         /// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3}"/> value type.
707         /// </summary>
708         /// <param name="item1">The value of the tuple's first component.</param>
709         /// <param name="item2">The value of the tuple's second component.</param>
710         /// <param name="item3">The value of the tuple's third component.</param>
ValueTupleSystem.ValueTuple711         public ValueTuple(T1 item1, T2 item2, T3 item3)
712         {
713             Item1 = item1;
714             Item2 = item2;
715             Item3 = item3;
716         }
717 
718         /// <summary>
719         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3}"/> instance is equal to a specified object.
720         /// </summary>
721         /// <param name="obj">The object to compare with this instance.</param>
722         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
723         /// <remarks>
724         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
725         /// <list type="bullet">
726         ///     <item><description>It is a <see cref="ValueTuple{T1, T2, T3}"/> value type.</description></item>
727         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
728         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
729         /// </list>
730         /// </remarks>
EqualsSystem.ValueTuple731         public override bool Equals(object obj)
732         {
733             return obj is ValueTuple<T1, T2, T3> && Equals((ValueTuple<T1, T2, T3>)obj);
734         }
735 
736         /// <summary>
737         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3}"/>
738         /// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3}"/>.
739         /// </summary>
740         /// <param name="other">The tuple to compare with this instance.</param>
741         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
742         /// <remarks>
743         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
744         /// are equal to that of the current instance, using the default comparer for that field's type.
745         /// </remarks>
EqualsSystem.ValueTuple746         public bool Equals(ValueTuple<T1, T2, T3> other)
747         {
748             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
749                 && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
750                 && EqualityComparer<T3>.Default.Equals(Item3, other.Item3);
751         }
752 
IStructuralEquatable.EqualsSystem.ValueTuple753         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
754         {
755             if (other == null || !(other is ValueTuple<T1, T2, T3>)) return false;
756 
757             var objTuple = (ValueTuple<T1, T2, T3>)other;
758 
759             return comparer.Equals(Item1, objTuple.Item1)
760                 && comparer.Equals(Item2, objTuple.Item2)
761                 && comparer.Equals(Item3, objTuple.Item3);
762         }
763 
IComparable.CompareToSystem.ValueTuple764         int IComparable.CompareTo(object other)
765         {
766             if (other == null) return 1;
767 
768             if (!(other is ValueTuple<T1, T2, T3>))
769             {
770                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
771             }
772 
773             return CompareTo((ValueTuple<T1, T2, T3>)other);
774         }
775 
776         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
777         /// <param name="other">An instance to compare.</param>
778         /// <returns>
779         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
780         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
781         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
782         /// than <paramref name="other"/>.
783         /// </returns>
CompareToSystem.ValueTuple784         public int CompareTo(ValueTuple<T1, T2, T3> other)
785         {
786             int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
787             if (c != 0) return c;
788 
789             c = Comparer<T2>.Default.Compare(Item2, other.Item2);
790             if (c != 0) return c;
791 
792             return Comparer<T3>.Default.Compare(Item3, other.Item3);
793         }
794 
IStructuralComparable.CompareToSystem.ValueTuple795         int IStructuralComparable.CompareTo(object other, IComparer comparer)
796         {
797             if (other == null) return 1;
798 
799             if (!(other is ValueTuple<T1, T2, T3>))
800             {
801                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
802             }
803 
804             var objTuple = (ValueTuple<T1, T2, T3>)other;
805 
806             int c = comparer.Compare(Item1, objTuple.Item1);
807             if (c != 0) return c;
808 
809             c = comparer.Compare(Item2, objTuple.Item2);
810             if (c != 0) return c;
811 
812             return comparer.Compare(Item3, objTuple.Item3);
813         }
814 
815         /// <summary>
816         /// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3}"/> instance.
817         /// </summary>
818         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple819         public override int GetHashCode()
820         {
821             return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
822                                                Item2?.GetHashCode() ?? 0,
823                                                Item3?.GetHashCode() ?? 0);
824         }
825 
IStructuralEquatable.GetHashCodeSystem.ValueTuple826         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
827         {
828             return GetHashCodeCore(comparer);
829         }
830 
GetHashCodeCoreSystem.ValueTuple831         private int GetHashCodeCore(IEqualityComparer comparer)
832         {
833             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
834                                                comparer.GetHashCode(Item2),
835                                                comparer.GetHashCode(Item3));
836         }
837 
IValueTupleInternal.GetHashCodeSystem.ValueTuple838         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
839         {
840             return GetHashCodeCore(comparer);
841         }
842 
843         /// <summary>
844         /// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3}"/> instance.
845         /// </summary>
846         /// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3}"/> instance.</returns>
847         /// <remarks>
848         /// The string returned by this method takes the form <c>(Item1, Item2, Item3)</c>.
849         /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
850         /// </remarks>
ToStringSystem.ValueTuple851         public override string ToString()
852         {
853             return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")";
854         }
855 
IValueTupleInternal.ToStringEndSystem.ValueTuple856         string IValueTupleInternal.ToStringEnd()
857         {
858             return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")";
859         }
860 
861         /// <summary>
862         /// The number of positions in this data structure.
863         /// </summary>
864         int ITuple.Length => 3;
865 
866         /// <summary>
867         /// Get the element at position <param name="index"/>.
868         /// </summary>
869         object ITuple.this[int index]
870         {
871             get
872             {
873                 switch (index)
874                 {
875                     case 0:
876                         return Item1;
877                     case 1:
878                         return Item2;
879                     case 2:
880                         return Item3;
881                     default:
882                         throw new IndexOutOfRangeException();
883                 }
884             }
885         }
886     }
887 
888     /// <summary>
889     /// Represents a 4-tuple, or quadruple, as a value type.
890     /// </summary>
891     /// <typeparam name="T1">The type of the tuple's first component.</typeparam>
892     /// <typeparam name="T2">The type of the tuple's second component.</typeparam>
893     /// <typeparam name="T3">The type of the tuple's third component.</typeparam>
894     /// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
895     [Serializable]
896     [StructLayout(LayoutKind.Auto)]
897 #if !MONO
898     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
899 #endif
900     public struct ValueTuple<T1, T2, T3, T4>
901         : IEquatable<ValueTuple<T1, T2, T3, T4>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4>>, IValueTupleInternal, ITuple
902     {
903         /// <summary>
904         /// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's first component.
905         /// </summary>
906         public T1 Item1;
907         /// <summary>
908         /// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's second component.
909         /// </summary>
910         public T2 Item2;
911         /// <summary>
912         /// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's third component.
913         /// </summary>
914         public T3 Item3;
915         /// <summary>
916         /// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's fourth component.
917         /// </summary>
918         public T4 Item4;
919 
920         /// <summary>
921         /// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4}"/> value type.
922         /// </summary>
923         /// <param name="item1">The value of the tuple's first component.</param>
924         /// <param name="item2">The value of the tuple's second component.</param>
925         /// <param name="item3">The value of the tuple's third component.</param>
926         /// <param name="item4">The value of the tuple's fourth component.</param>
ValueTupleSystem.ValueTuple927         public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4)
928         {
929             Item1 = item1;
930             Item2 = item2;
931             Item3 = item3;
932             Item4 = item4;
933         }
934 
935         /// <summary>
936         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance is equal to a specified object.
937         /// </summary>
938         /// <param name="obj">The object to compare with this instance.</param>
939         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
940         /// <remarks>
941         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
942         /// <list type="bullet">
943         ///     <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4}"/> value type.</description></item>
944         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
945         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
946         /// </list>
947         /// </remarks>
EqualsSystem.ValueTuple948         public override bool Equals(object obj)
949         {
950             return obj is ValueTuple<T1, T2, T3, T4> && Equals((ValueTuple<T1, T2, T3, T4>)obj);
951         }
952 
953         /// <summary>
954         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4}"/>
955         /// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4}"/>.
956         /// </summary>
957         /// <param name="other">The tuple to compare with this instance.</param>
958         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
959         /// <remarks>
960         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
961         /// are equal to that of the current instance, using the default comparer for that field's type.
962         /// </remarks>
EqualsSystem.ValueTuple963         public bool Equals(ValueTuple<T1, T2, T3, T4> other)
964         {
965             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
966                 && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
967                 && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
968                 && EqualityComparer<T4>.Default.Equals(Item4, other.Item4);
969         }
970 
IStructuralEquatable.EqualsSystem.ValueTuple971         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
972         {
973             if (other == null || !(other is ValueTuple<T1, T2, T3, T4>)) return false;
974 
975             var objTuple = (ValueTuple<T1, T2, T3, T4>)other;
976 
977             return comparer.Equals(Item1, objTuple.Item1)
978                 && comparer.Equals(Item2, objTuple.Item2)
979                 && comparer.Equals(Item3, objTuple.Item3)
980                 && comparer.Equals(Item4, objTuple.Item4);
981         }
982 
IComparable.CompareToSystem.ValueTuple983         int IComparable.CompareTo(object other)
984         {
985             if (other == null) return 1;
986 
987             if (!(other is ValueTuple<T1, T2, T3, T4>))
988             {
989                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
990             }
991 
992             return CompareTo((ValueTuple<T1, T2, T3, T4>)other);
993         }
994 
995         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
996         /// <param name="other">An instance to compare.</param>
997         /// <returns>
998         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
999         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
1000         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
1001         /// than <paramref name="other"/>.
1002         /// </returns>
CompareToSystem.ValueTuple1003         public int CompareTo(ValueTuple<T1, T2, T3, T4> other)
1004         {
1005             int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
1006             if (c != 0) return c;
1007 
1008             c = Comparer<T2>.Default.Compare(Item2, other.Item2);
1009             if (c != 0) return c;
1010 
1011             c = Comparer<T3>.Default.Compare(Item3, other.Item3);
1012             if (c != 0) return c;
1013 
1014             return Comparer<T4>.Default.Compare(Item4, other.Item4);
1015         }
1016 
IStructuralComparable.CompareToSystem.ValueTuple1017         int IStructuralComparable.CompareTo(object other, IComparer comparer)
1018         {
1019             if (other == null) return 1;
1020 
1021             if (!(other is ValueTuple<T1, T2, T3, T4>))
1022             {
1023                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
1024             }
1025 
1026             var objTuple = (ValueTuple<T1, T2, T3, T4>)other;
1027 
1028             int c = comparer.Compare(Item1, objTuple.Item1);
1029             if (c != 0) return c;
1030 
1031             c = comparer.Compare(Item2, objTuple.Item2);
1032             if (c != 0) return c;
1033 
1034             c = comparer.Compare(Item3, objTuple.Item3);
1035             if (c != 0) return c;
1036 
1037             return comparer.Compare(Item4, objTuple.Item4);
1038         }
1039 
1040         /// <summary>
1041         /// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.
1042         /// </summary>
1043         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple1044         public override int GetHashCode()
1045         {
1046             return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
1047                                                Item2?.GetHashCode() ?? 0,
1048                                                Item3?.GetHashCode() ?? 0,
1049                                                Item4?.GetHashCode() ?? 0);
1050         }
1051 
IStructuralEquatable.GetHashCodeSystem.ValueTuple1052         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
1053         {
1054             return GetHashCodeCore(comparer);
1055         }
1056 
GetHashCodeCoreSystem.ValueTuple1057         private int GetHashCodeCore(IEqualityComparer comparer)
1058         {
1059             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
1060                                                comparer.GetHashCode(Item2),
1061                                                comparer.GetHashCode(Item3),
1062                                                comparer.GetHashCode(Item4));
1063         }
1064 
IValueTupleInternal.GetHashCodeSystem.ValueTuple1065         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
1066         {
1067             return GetHashCodeCore(comparer);
1068         }
1069 
1070         /// <summary>
1071         /// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.
1072         /// </summary>
1073         /// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.</returns>
1074         /// <remarks>
1075         /// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4)</c>.
1076         /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
1077         /// </remarks>
ToStringSystem.ValueTuple1078         public override string ToString()
1079         {
1080             return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")";
1081         }
1082 
IValueTupleInternal.ToStringEndSystem.ValueTuple1083         string IValueTupleInternal.ToStringEnd()
1084         {
1085             return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")";
1086         }
1087 
1088         /// <summary>
1089         /// The number of positions in this data structure.
1090         /// </summary>
1091         int ITuple.Length => 4;
1092 
1093         /// <summary>
1094         /// Get the element at position <param name="index"/>.
1095         /// </summary>
1096         object ITuple.this[int index]
1097         {
1098             get
1099             {
1100                 switch (index)
1101                 {
1102                     case 0:
1103                         return Item1;
1104                     case 1:
1105                         return Item2;
1106                     case 2:
1107                         return Item3;
1108                     case 3:
1109                         return Item4;
1110                     default:
1111                         throw new IndexOutOfRangeException();
1112                 }
1113             }
1114         }
1115     }
1116 
1117     /// <summary>
1118     /// Represents a 5-tuple, or quintuple, as a value type.
1119     /// </summary>
1120     /// <typeparam name="T1">The type of the tuple's first component.</typeparam>
1121     /// <typeparam name="T2">The type of the tuple's second component.</typeparam>
1122     /// <typeparam name="T3">The type of the tuple's third component.</typeparam>
1123     /// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
1124     /// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
1125     [Serializable]
1126     [StructLayout(LayoutKind.Auto)]
1127 #if !MONO
1128     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
1129 #endif
1130     public struct ValueTuple<T1, T2, T3, T4, T5>
1131         : IEquatable<ValueTuple<T1, T2, T3, T4, T5>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5>>, IValueTupleInternal, ITuple
1132     {
1133         /// <summary>
1134         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's first component.
1135         /// </summary>
1136         public T1 Item1;
1137         /// <summary>
1138         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's second component.
1139         /// </summary>
1140         public T2 Item2;
1141         /// <summary>
1142         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's third component.
1143         /// </summary>
1144         public T3 Item3;
1145         /// <summary>
1146         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's fourth component.
1147         /// </summary>
1148         public T4 Item4;
1149         /// <summary>
1150         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's fifth component.
1151         /// </summary>
1152         public T5 Item5;
1153 
1154         /// <summary>
1155         /// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> value type.
1156         /// </summary>
1157         /// <param name="item1">The value of the tuple's first component.</param>
1158         /// <param name="item2">The value of the tuple's second component.</param>
1159         /// <param name="item3">The value of the tuple's third component.</param>
1160         /// <param name="item4">The value of the tuple's fourth component.</param>
1161         /// <param name="item5">The value of the tuple's fifth component.</param>
ValueTupleSystem.ValueTuple1162         public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
1163         {
1164             Item1 = item1;
1165             Item2 = item2;
1166             Item3 = item3;
1167             Item4 = item4;
1168             Item5 = item5;
1169         }
1170 
1171         /// <summary>
1172         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance is equal to a specified object.
1173         /// </summary>
1174         /// <param name="obj">The object to compare with this instance.</param>
1175         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
1176         /// <remarks>
1177         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
1178         /// <list type="bullet">
1179         ///     <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> value type.</description></item>
1180         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
1181         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
1182         /// </list>
1183         /// </remarks>
EqualsSystem.ValueTuple1184         public override bool Equals(object obj)
1185         {
1186             return obj is ValueTuple<T1, T2, T3, T4, T5> && Equals((ValueTuple<T1, T2, T3, T4, T5>)obj);
1187         }
1188 
1189         /// <summary>
1190         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/>
1191         /// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4, T5}"/>.
1192         /// </summary>
1193         /// <param name="other">The tuple to compare with this instance.</param>
1194         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
1195         /// <remarks>
1196         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
1197         /// are equal to that of the current instance, using the default comparer for that field's type.
1198         /// </remarks>
EqualsSystem.ValueTuple1199         public bool Equals(ValueTuple<T1, T2, T3, T4, T5> other)
1200         {
1201             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
1202                 && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
1203                 && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
1204                 && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
1205                 && EqualityComparer<T5>.Default.Equals(Item5, other.Item5);
1206         }
1207 
IStructuralEquatable.EqualsSystem.ValueTuple1208         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
1209         {
1210             if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5>)) return false;
1211 
1212             var objTuple = (ValueTuple<T1, T2, T3, T4, T5>)other;
1213 
1214             return comparer.Equals(Item1, objTuple.Item1)
1215                 && comparer.Equals(Item2, objTuple.Item2)
1216                 && comparer.Equals(Item3, objTuple.Item3)
1217                 && comparer.Equals(Item4, objTuple.Item4)
1218                 && comparer.Equals(Item5, objTuple.Item5);
1219         }
1220 
IComparable.CompareToSystem.ValueTuple1221         int IComparable.CompareTo(object other)
1222         {
1223             if (other == null) return 1;
1224 
1225             if (!(other is ValueTuple<T1, T2, T3, T4, T5>))
1226             {
1227                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
1228             }
1229 
1230             return CompareTo((ValueTuple<T1, T2, T3, T4, T5>)other);
1231         }
1232 
1233         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
1234         /// <param name="other">An instance to compare.</param>
1235         /// <returns>
1236         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
1237         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
1238         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
1239         /// than <paramref name="other"/>.
1240         /// </returns>
CompareToSystem.ValueTuple1241         public int CompareTo(ValueTuple<T1, T2, T3, T4, T5> other)
1242         {
1243             int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
1244             if (c != 0) return c;
1245 
1246             c = Comparer<T2>.Default.Compare(Item2, other.Item2);
1247             if (c != 0) return c;
1248 
1249             c = Comparer<T3>.Default.Compare(Item3, other.Item3);
1250             if (c != 0) return c;
1251 
1252             c = Comparer<T4>.Default.Compare(Item4, other.Item4);
1253             if (c != 0) return c;
1254 
1255             return Comparer<T5>.Default.Compare(Item5, other.Item5);
1256         }
1257 
IStructuralComparable.CompareToSystem.ValueTuple1258         int IStructuralComparable.CompareTo(object other, IComparer comparer)
1259         {
1260             if (other == null) return 1;
1261 
1262             if (!(other is ValueTuple<T1, T2, T3, T4, T5>))
1263             {
1264                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
1265             }
1266 
1267             var objTuple = (ValueTuple<T1, T2, T3, T4, T5>)other;
1268 
1269             int c = comparer.Compare(Item1, objTuple.Item1);
1270             if (c != 0) return c;
1271 
1272             c = comparer.Compare(Item2, objTuple.Item2);
1273             if (c != 0) return c;
1274 
1275             c = comparer.Compare(Item3, objTuple.Item3);
1276             if (c != 0) return c;
1277 
1278             c = comparer.Compare(Item4, objTuple.Item4);
1279             if (c != 0) return c;
1280 
1281             return comparer.Compare(Item5, objTuple.Item5);
1282         }
1283 
1284         /// <summary>
1285         /// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.
1286         /// </summary>
1287         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple1288         public override int GetHashCode()
1289         {
1290             return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
1291                                                Item2?.GetHashCode() ?? 0,
1292                                                Item3?.GetHashCode() ?? 0,
1293                                                Item4?.GetHashCode() ?? 0,
1294                                                Item5?.GetHashCode() ?? 0);
1295         }
1296 
IStructuralEquatable.GetHashCodeSystem.ValueTuple1297         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
1298         {
1299             return GetHashCodeCore(comparer);
1300         }
1301 
GetHashCodeCoreSystem.ValueTuple1302         private int GetHashCodeCore(IEqualityComparer comparer)
1303         {
1304             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
1305                                                comparer.GetHashCode(Item2),
1306                                                comparer.GetHashCode(Item3),
1307                                                comparer.GetHashCode(Item4),
1308                                                comparer.GetHashCode(Item5));
1309         }
1310 
IValueTupleInternal.GetHashCodeSystem.ValueTuple1311         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
1312         {
1313             return GetHashCodeCore(comparer);
1314         }
1315 
1316         /// <summary>
1317         /// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.
1318         /// </summary>
1319         /// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.</returns>
1320         /// <remarks>
1321         /// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5)</c>.
1322         /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
1323         /// </remarks>
ToStringSystem.ValueTuple1324         public override string ToString()
1325         {
1326             return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")";
1327         }
1328 
IValueTupleInternal.ToStringEndSystem.ValueTuple1329         string IValueTupleInternal.ToStringEnd()
1330         {
1331             return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")";
1332         }
1333 
1334         /// <summary>
1335         /// The number of positions in this data structure.
1336         /// </summary>
1337         int ITuple.Length => 5;
1338 
1339         /// <summary>
1340         /// Get the element at position <param name="index"/>.
1341         /// </summary>
1342         object ITuple.this[int index]
1343         {
1344             get
1345             {
1346                 switch (index)
1347                 {
1348                     case 0:
1349                         return Item1;
1350                     case 1:
1351                         return Item2;
1352                     case 2:
1353                         return Item3;
1354                     case 3:
1355                         return Item4;
1356                     case 4:
1357                         return Item5;
1358                     default:
1359                         throw new IndexOutOfRangeException();
1360                 }
1361             }
1362         }
1363     }
1364 
1365     /// <summary>
1366     /// Represents a 6-tuple, or sixtuple, as a value type.
1367     /// </summary>
1368     /// <typeparam name="T1">The type of the tuple's first component.</typeparam>
1369     /// <typeparam name="T2">The type of the tuple's second component.</typeparam>
1370     /// <typeparam name="T3">The type of the tuple's third component.</typeparam>
1371     /// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
1372     /// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
1373     /// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
1374     [Serializable]
1375     [StructLayout(LayoutKind.Auto)]
1376 #if !MONO
1377     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
1378 #endif
1379     public struct ValueTuple<T1, T2, T3, T4, T5, T6>
1380         : IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IValueTupleInternal, ITuple
1381     {
1382         /// <summary>
1383         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's first component.
1384         /// </summary>
1385         public T1 Item1;
1386         /// <summary>
1387         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's second component.
1388         /// </summary>
1389         public T2 Item2;
1390         /// <summary>
1391         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's third component.
1392         /// </summary>
1393         public T3 Item3;
1394         /// <summary>
1395         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's fourth component.
1396         /// </summary>
1397         public T4 Item4;
1398         /// <summary>
1399         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's fifth component.
1400         /// </summary>
1401         public T5 Item5;
1402         /// <summary>
1403         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's sixth component.
1404         /// </summary>
1405         public T6 Item6;
1406 
1407         /// <summary>
1408         /// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> value type.
1409         /// </summary>
1410         /// <param name="item1">The value of the tuple's first component.</param>
1411         /// <param name="item2">The value of the tuple's second component.</param>
1412         /// <param name="item3">The value of the tuple's third component.</param>
1413         /// <param name="item4">The value of the tuple's fourth component.</param>
1414         /// <param name="item5">The value of the tuple's fifth component.</param>
1415         /// <param name="item6">The value of the tuple's sixth component.</param>
ValueTupleSystem.ValueTuple1416         public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
1417         {
1418             Item1 = item1;
1419             Item2 = item2;
1420             Item3 = item3;
1421             Item4 = item4;
1422             Item5 = item5;
1423             Item6 = item6;
1424         }
1425 
1426         /// <summary>
1427         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance is equal to a specified object.
1428         /// </summary>
1429         /// <param name="obj">The object to compare with this instance.</param>
1430         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
1431         /// <remarks>
1432         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
1433         /// <list type="bullet">
1434         ///     <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> value type.</description></item>
1435         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
1436         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
1437         /// </list>
1438         /// </remarks>
EqualsSystem.ValueTuple1439         public override bool Equals(object obj)
1440         {
1441             return obj is ValueTuple<T1, T2, T3, T4, T5, T6> && Equals((ValueTuple<T1, T2, T3, T4, T5, T6>)obj);
1442         }
1443 
1444         /// <summary>
1445         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/>
1446         /// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/>.
1447         /// </summary>
1448         /// <param name="other">The tuple to compare with this instance.</param>
1449         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
1450         /// <remarks>
1451         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
1452         /// are equal to that of the current instance, using the default comparer for that field's type.
1453         /// </remarks>
EqualsSystem.ValueTuple1454         public bool Equals(ValueTuple<T1, T2, T3, T4, T5, T6> other)
1455         {
1456             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
1457                 && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
1458                 && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
1459                 && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
1460                 && EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
1461                 && EqualityComparer<T6>.Default.Equals(Item6, other.Item6);
1462         }
1463 
IStructuralEquatable.EqualsSystem.ValueTuple1464         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
1465         {
1466             if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5, T6>)) return false;
1467 
1468             var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6>)other;
1469 
1470             return comparer.Equals(Item1, objTuple.Item1)
1471                 && comparer.Equals(Item2, objTuple.Item2)
1472                 && comparer.Equals(Item3, objTuple.Item3)
1473                 && comparer.Equals(Item4, objTuple.Item4)
1474                 && comparer.Equals(Item5, objTuple.Item5)
1475                 && comparer.Equals(Item6, objTuple.Item6);
1476         }
1477 
IComparable.CompareToSystem.ValueTuple1478         int IComparable.CompareTo(object other)
1479         {
1480             if (other == null) return 1;
1481 
1482             if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6>))
1483             {
1484                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
1485             }
1486 
1487             return CompareTo((ValueTuple<T1, T2, T3, T4, T5, T6>)other);
1488         }
1489 
1490         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
1491         /// <param name="other">An instance to compare.</param>
1492         /// <returns>
1493         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
1494         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
1495         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
1496         /// than <paramref name="other"/>.
1497         /// </returns>
CompareToSystem.ValueTuple1498         public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6> other)
1499         {
1500             int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
1501             if (c != 0) return c;
1502 
1503             c = Comparer<T2>.Default.Compare(Item2, other.Item2);
1504             if (c != 0) return c;
1505 
1506             c = Comparer<T3>.Default.Compare(Item3, other.Item3);
1507             if (c != 0) return c;
1508 
1509             c = Comparer<T4>.Default.Compare(Item4, other.Item4);
1510             if (c != 0) return c;
1511 
1512             c = Comparer<T5>.Default.Compare(Item5, other.Item5);
1513             if (c != 0) return c;
1514 
1515             return Comparer<T6>.Default.Compare(Item6, other.Item6);
1516         }
1517 
IStructuralComparable.CompareToSystem.ValueTuple1518         int IStructuralComparable.CompareTo(object other, IComparer comparer)
1519         {
1520             if (other == null) return 1;
1521 
1522             if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6>))
1523             {
1524                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
1525             }
1526 
1527             var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6>)other;
1528 
1529             int c = comparer.Compare(Item1, objTuple.Item1);
1530             if (c != 0) return c;
1531 
1532             c = comparer.Compare(Item2, objTuple.Item2);
1533             if (c != 0) return c;
1534 
1535             c = comparer.Compare(Item3, objTuple.Item3);
1536             if (c != 0) return c;
1537 
1538             c = comparer.Compare(Item4, objTuple.Item4);
1539             if (c != 0) return c;
1540 
1541             c = comparer.Compare(Item5, objTuple.Item5);
1542             if (c != 0) return c;
1543 
1544             return comparer.Compare(Item6, objTuple.Item6);
1545         }
1546 
1547         /// <summary>
1548         /// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.
1549         /// </summary>
1550         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple1551         public override int GetHashCode()
1552         {
1553             return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
1554                                                Item2?.GetHashCode() ?? 0,
1555                                                Item3?.GetHashCode() ?? 0,
1556                                                Item4?.GetHashCode() ?? 0,
1557                                                Item5?.GetHashCode() ?? 0,
1558                                                Item6?.GetHashCode() ?? 0);
1559         }
1560 
IStructuralEquatable.GetHashCodeSystem.ValueTuple1561         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
1562         {
1563             return GetHashCodeCore(comparer);
1564         }
1565 
GetHashCodeCoreSystem.ValueTuple1566         private int GetHashCodeCore(IEqualityComparer comparer)
1567         {
1568             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
1569                                                comparer.GetHashCode(Item2),
1570                                                comparer.GetHashCode(Item3),
1571                                                comparer.GetHashCode(Item4),
1572                                                comparer.GetHashCode(Item5),
1573                                                comparer.GetHashCode(Item6));
1574         }
1575 
IValueTupleInternal.GetHashCodeSystem.ValueTuple1576         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
1577         {
1578             return GetHashCodeCore(comparer);
1579         }
1580 
1581         /// <summary>
1582         /// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.
1583         /// </summary>
1584         /// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.</returns>
1585         /// <remarks>
1586         /// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6)</c>.
1587         /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
1588         /// </remarks>
ToStringSystem.ValueTuple1589         public override string ToString()
1590         {
1591             return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")";
1592         }
1593 
IValueTupleInternal.ToStringEndSystem.ValueTuple1594         string IValueTupleInternal.ToStringEnd()
1595         {
1596             return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")";
1597         }
1598 
1599         /// <summary>
1600         /// The number of positions in this data structure.
1601         /// </summary>
1602         int ITuple.Length => 6;
1603 
1604         /// <summary>
1605         /// Get the element at position <param name="index"/>.
1606         /// </summary>
1607         object ITuple.this[int index]
1608         {
1609             get
1610             {
1611                 switch (index)
1612                 {
1613                     case 0:
1614                         return Item1;
1615                     case 1:
1616                         return Item2;
1617                     case 2:
1618                         return Item3;
1619                     case 3:
1620                         return Item4;
1621                     case 4:
1622                         return Item5;
1623                     case 5:
1624                         return Item6;
1625                     default:
1626                         throw new IndexOutOfRangeException();
1627                 }
1628             }
1629         }
1630     }
1631 
1632     /// <summary>
1633     /// Represents a 7-tuple, or sentuple, as a value type.
1634     /// </summary>
1635     /// <typeparam name="T1">The type of the tuple's first component.</typeparam>
1636     /// <typeparam name="T2">The type of the tuple's second component.</typeparam>
1637     /// <typeparam name="T3">The type of the tuple's third component.</typeparam>
1638     /// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
1639     /// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
1640     /// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
1641     /// <typeparam name="T7">The type of the tuple's seventh component.</typeparam>
1642     [Serializable]
1643     [StructLayout(LayoutKind.Auto)]
1644 #if !MONO
1645     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
1646 #endif
1647     public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7>
1648         : IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IValueTupleInternal, ITuple
1649     {
1650         /// <summary>
1651         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's first component.
1652         /// </summary>
1653         public T1 Item1;
1654         /// <summary>
1655         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's second component.
1656         /// </summary>
1657         public T2 Item2;
1658         /// <summary>
1659         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's third component.
1660         /// </summary>
1661         public T3 Item3;
1662         /// <summary>
1663         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's fourth component.
1664         /// </summary>
1665         public T4 Item4;
1666         /// <summary>
1667         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's fifth component.
1668         /// </summary>
1669         public T5 Item5;
1670         /// <summary>
1671         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's sixth component.
1672         /// </summary>
1673         public T6 Item6;
1674         /// <summary>
1675         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's seventh component.
1676         /// </summary>
1677         public T7 Item7;
1678 
1679         /// <summary>
1680         /// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> value type.
1681         /// </summary>
1682         /// <param name="item1">The value of the tuple's first component.</param>
1683         /// <param name="item2">The value of the tuple's second component.</param>
1684         /// <param name="item3">The value of the tuple's third component.</param>
1685         /// <param name="item4">The value of the tuple's fourth component.</param>
1686         /// <param name="item5">The value of the tuple's fifth component.</param>
1687         /// <param name="item6">The value of the tuple's sixth component.</param>
1688         /// <param name="item7">The value of the tuple's seventh component.</param>
ValueTupleSystem.ValueTuple1689         public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
1690         {
1691             Item1 = item1;
1692             Item2 = item2;
1693             Item3 = item3;
1694             Item4 = item4;
1695             Item5 = item5;
1696             Item6 = item6;
1697             Item7 = item7;
1698         }
1699 
1700         /// <summary>
1701         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance is equal to a specified object.
1702         /// </summary>
1703         /// <param name="obj">The object to compare with this instance.</param>
1704         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
1705         /// <remarks>
1706         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
1707         /// <list type="bullet">
1708         ///     <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> value type.</description></item>
1709         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
1710         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
1711         /// </list>
1712         /// </remarks>
EqualsSystem.ValueTuple1713         public override bool Equals(object obj)
1714         {
1715             return obj is ValueTuple<T1, T2, T3, T4, T5, T6, T7> && Equals((ValueTuple<T1, T2, T3, T4, T5, T6, T7>)obj);
1716         }
1717 
1718         /// <summary>
1719         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/>
1720         /// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/>.
1721         /// </summary>
1722         /// <param name="other">The tuple to compare with this instance.</param>
1723         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
1724         /// <remarks>
1725         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
1726         /// are equal to that of the current instance, using the default comparer for that field's type.
1727         /// </remarks>
EqualsSystem.ValueTuple1728         public bool Equals(ValueTuple<T1, T2, T3, T4, T5, T6, T7> other)
1729         {
1730             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
1731                 && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
1732                 && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
1733                 && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
1734                 && EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
1735                 && EqualityComparer<T6>.Default.Equals(Item6, other.Item6)
1736                 && EqualityComparer<T7>.Default.Equals(Item7, other.Item7);
1737         }
1738 
IStructuralEquatable.EqualsSystem.ValueTuple1739         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
1740         {
1741             if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7>)) return false;
1742 
1743             var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7>)other;
1744 
1745             return comparer.Equals(Item1, objTuple.Item1)
1746                 && comparer.Equals(Item2, objTuple.Item2)
1747                 && comparer.Equals(Item3, objTuple.Item3)
1748                 && comparer.Equals(Item4, objTuple.Item4)
1749                 && comparer.Equals(Item5, objTuple.Item5)
1750                 && comparer.Equals(Item6, objTuple.Item6)
1751                 && comparer.Equals(Item7, objTuple.Item7);
1752         }
1753 
IComparable.CompareToSystem.ValueTuple1754         int IComparable.CompareTo(object other)
1755         {
1756             if (other == null) return 1;
1757 
1758             if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7>))
1759             {
1760                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
1761             }
1762 
1763             return CompareTo((ValueTuple<T1, T2, T3, T4, T5, T6, T7>)other);
1764         }
1765 
1766         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
1767         /// <param name="other">An instance to compare.</param>
1768         /// <returns>
1769         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
1770         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
1771         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
1772         /// than <paramref name="other"/>.
1773         /// </returns>
CompareToSystem.ValueTuple1774         public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6, T7> other)
1775         {
1776             int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
1777             if (c != 0) return c;
1778 
1779             c = Comparer<T2>.Default.Compare(Item2, other.Item2);
1780             if (c != 0) return c;
1781 
1782             c = Comparer<T3>.Default.Compare(Item3, other.Item3);
1783             if (c != 0) return c;
1784 
1785             c = Comparer<T4>.Default.Compare(Item4, other.Item4);
1786             if (c != 0) return c;
1787 
1788             c = Comparer<T5>.Default.Compare(Item5, other.Item5);
1789             if (c != 0) return c;
1790 
1791             c = Comparer<T6>.Default.Compare(Item6, other.Item6);
1792             if (c != 0) return c;
1793 
1794             return Comparer<T7>.Default.Compare(Item7, other.Item7);
1795         }
1796 
IStructuralComparable.CompareToSystem.ValueTuple1797         int IStructuralComparable.CompareTo(object other, IComparer comparer)
1798         {
1799             if (other == null) return 1;
1800 
1801             if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7>))
1802             {
1803                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
1804             }
1805 
1806             var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7>)other;
1807 
1808             int c = comparer.Compare(Item1, objTuple.Item1);
1809             if (c != 0) return c;
1810 
1811             c = comparer.Compare(Item2, objTuple.Item2);
1812             if (c != 0) return c;
1813 
1814             c = comparer.Compare(Item3, objTuple.Item3);
1815             if (c != 0) return c;
1816 
1817             c = comparer.Compare(Item4, objTuple.Item4);
1818             if (c != 0) return c;
1819 
1820             c = comparer.Compare(Item5, objTuple.Item5);
1821             if (c != 0) return c;
1822 
1823             c = comparer.Compare(Item6, objTuple.Item6);
1824             if (c != 0) return c;
1825 
1826             return comparer.Compare(Item7, objTuple.Item7);
1827         }
1828 
1829         /// <summary>
1830         /// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.
1831         /// </summary>
1832         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple1833         public override int GetHashCode()
1834         {
1835             return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
1836                                                 Item2?.GetHashCode() ?? 0,
1837                                                 Item3?.GetHashCode() ?? 0,
1838                                                 Item4?.GetHashCode() ?? 0,
1839                                                 Item5?.GetHashCode() ?? 0,
1840                                                 Item6?.GetHashCode() ?? 0,
1841                                                 Item7?.GetHashCode() ?? 0);
1842         }
1843 
IStructuralEquatable.GetHashCodeSystem.ValueTuple1844         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
1845         {
1846             return GetHashCodeCore(comparer);
1847         }
1848 
GetHashCodeCoreSystem.ValueTuple1849         private int GetHashCodeCore(IEqualityComparer comparer)
1850         {
1851             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
1852                                                comparer.GetHashCode(Item2),
1853                                                comparer.GetHashCode(Item3),
1854                                                comparer.GetHashCode(Item4),
1855                                                comparer.GetHashCode(Item5),
1856                                                comparer.GetHashCode(Item6),
1857                                                comparer.GetHashCode(Item7));
1858         }
1859 
IValueTupleInternal.GetHashCodeSystem.ValueTuple1860         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
1861         {
1862             return GetHashCodeCore(comparer);
1863         }
1864 
1865         /// <summary>
1866         /// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.
1867         /// </summary>
1868         /// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.</returns>
1869         /// <remarks>
1870         /// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7)</c>.
1871         /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
1872         /// </remarks>
ToStringSystem.ValueTuple1873         public override string ToString()
1874         {
1875             return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")";
1876         }
1877 
IValueTupleInternal.ToStringEndSystem.ValueTuple1878         string IValueTupleInternal.ToStringEnd()
1879         {
1880             return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")";
1881         }
1882 
1883         /// <summary>
1884         /// The number of positions in this data structure.
1885         /// </summary>
1886         int ITuple.Length => 7;
1887 
1888         /// <summary>
1889         /// Get the element at position <param name="index"/>.
1890         /// </summary>
1891         object ITuple.this[int index]
1892         {
1893             get
1894             {
1895                 switch (index)
1896                 {
1897                     case 0:
1898                         return Item1;
1899                     case 1:
1900                         return Item2;
1901                     case 2:
1902                         return Item3;
1903                     case 3:
1904                         return Item4;
1905                     case 4:
1906                         return Item5;
1907                     case 5:
1908                         return Item6;
1909                     case 6:
1910                         return Item7;
1911                     default:
1912                         throw new IndexOutOfRangeException();
1913                 }
1914             }
1915         }
1916     }
1917 
1918     /// <summary>
1919     /// Represents an 8-tuple, or octuple, as a value type.
1920     /// </summary>
1921     /// <typeparam name="T1">The type of the tuple's first component.</typeparam>
1922     /// <typeparam name="T2">The type of the tuple's second component.</typeparam>
1923     /// <typeparam name="T3">The type of the tuple's third component.</typeparam>
1924     /// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
1925     /// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
1926     /// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
1927     /// <typeparam name="T7">The type of the tuple's seventh component.</typeparam>
1928     /// <typeparam name="TRest">The type of the tuple's eighth component.</typeparam>
1929     [Serializable]
1930     [StructLayout(LayoutKind.Auto)]
1931 #if !MONO
1932     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
1933 #endif
1934     public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>
1935     : IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IValueTupleInternal, ITuple
1936     where TRest : struct
1937     {
1938         /// <summary>
1939         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's first component.
1940         /// </summary>
1941         public T1 Item1;
1942         /// <summary>
1943         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's second component.
1944         /// </summary>
1945         public T2 Item2;
1946         /// <summary>
1947         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's third component.
1948         /// </summary>
1949         public T3 Item3;
1950         /// <summary>
1951         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's fourth component.
1952         /// </summary>
1953         public T4 Item4;
1954         /// <summary>
1955         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's fifth component.
1956         /// </summary>
1957         public T5 Item5;
1958         /// <summary>
1959         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's sixth component.
1960         /// </summary>
1961         public T6 Item6;
1962         /// <summary>
1963         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's seventh component.
1964         /// </summary>
1965         public T7 Item7;
1966         /// <summary>
1967         /// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's eighth component.
1968         /// </summary>
1969         public TRest Rest;
1970 
1971         /// <summary>
1972         /// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> value type.
1973         /// </summary>
1974         /// <param name="item1">The value of the tuple's first component.</param>
1975         /// <param name="item2">The value of the tuple's second component.</param>
1976         /// <param name="item3">The value of the tuple's third component.</param>
1977         /// <param name="item4">The value of the tuple's fourth component.</param>
1978         /// <param name="item5">The value of the tuple's fifth component.</param>
1979         /// <param name="item6">The value of the tuple's sixth component.</param>
1980         /// <param name="item7">The value of the tuple's seventh component.</param>
1981         /// <param name="rest">The value of the tuple's eight component.</param>
ValueTupleSystem.ValueTuple1982         public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest)
1983         {
1984             if (!(rest is IValueTupleInternal))
1985             {
1986                 throw new ArgumentException(SR.ArgumentException_ValueTupleLastArgumentNotAValueTuple);
1987             }
1988 
1989             Item1 = item1;
1990             Item2 = item2;
1991             Item3 = item3;
1992             Item4 = item4;
1993             Item5 = item5;
1994             Item6 = item6;
1995             Item7 = item7;
1996             Rest = rest;
1997         }
1998 
1999         /// <summary>
2000         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance is equal to a specified object.
2001         /// </summary>
2002         /// <param name="obj">The object to compare with this instance.</param>
2003         /// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
2004         /// <remarks>
2005         /// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
2006         /// <list type="bullet">
2007         ///     <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> value type.</description></item>
2008         ///     <item><description>Its components are of the same types as those of the current instance.</description></item>
2009         ///     <item><description>Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component.</description></item>
2010         /// </list>
2011         /// </remarks>
EqualsSystem.ValueTuple2012         public override bool Equals(object obj)
2013         {
2014             return obj is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> && Equals((ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)obj);
2015         }
2016 
2017         /// <summary>
2018         /// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/>
2019         /// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/>.
2020         /// </summary>
2021         /// <param name="other">The tuple to compare with this instance.</param>
2022         /// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
2023         /// <remarks>
2024         /// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
2025         /// are equal to that of the current instance, using the default comparer for that field's type.
2026         /// </remarks>
EqualsSystem.ValueTuple2027         public bool Equals(ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other)
2028         {
2029             return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
2030                 && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
2031                 && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
2032                 && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
2033                 && EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
2034                 && EqualityComparer<T6>.Default.Equals(Item6, other.Item6)
2035                 && EqualityComparer<T7>.Default.Equals(Item7, other.Item7)
2036                 && EqualityComparer<TRest>.Default.Equals(Rest, other.Rest);
2037         }
2038 
IStructuralEquatable.EqualsSystem.ValueTuple2039         bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
2040         {
2041             if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)) return false;
2042 
2043             var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)other;
2044 
2045             return comparer.Equals(Item1, objTuple.Item1)
2046                 && comparer.Equals(Item2, objTuple.Item2)
2047                 && comparer.Equals(Item3, objTuple.Item3)
2048                 && comparer.Equals(Item4, objTuple.Item4)
2049                 && comparer.Equals(Item5, objTuple.Item5)
2050                 && comparer.Equals(Item6, objTuple.Item6)
2051                 && comparer.Equals(Item7, objTuple.Item7)
2052                 && comparer.Equals(Rest, objTuple.Rest);
2053         }
2054 
IComparable.CompareToSystem.ValueTuple2055         int IComparable.CompareTo(object other)
2056         {
2057             if (other == null) return 1;
2058 
2059             if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>))
2060             {
2061                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
2062             }
2063 
2064             return CompareTo((ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)other);
2065         }
2066 
2067         /// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
2068         /// <param name="other">An instance to compare.</param>
2069         /// <returns>
2070         /// A signed number indicating the relative values of this instance and <paramref name="other"/>.
2071         /// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
2072         /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
2073         /// than <paramref name="other"/>.
2074         /// </returns>
CompareToSystem.ValueTuple2075         public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other)
2076         {
2077             int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
2078             if (c != 0) return c;
2079 
2080             c = Comparer<T2>.Default.Compare(Item2, other.Item2);
2081             if (c != 0) return c;
2082 
2083             c = Comparer<T3>.Default.Compare(Item3, other.Item3);
2084             if (c != 0) return c;
2085 
2086             c = Comparer<T4>.Default.Compare(Item4, other.Item4);
2087             if (c != 0) return c;
2088 
2089             c = Comparer<T5>.Default.Compare(Item5, other.Item5);
2090             if (c != 0) return c;
2091 
2092             c = Comparer<T6>.Default.Compare(Item6, other.Item6);
2093             if (c != 0) return c;
2094 
2095             c = Comparer<T7>.Default.Compare(Item7, other.Item7);
2096             if (c != 0) return c;
2097 
2098             return Comparer<TRest>.Default.Compare(Rest, other.Rest);
2099         }
2100 
IStructuralComparable.CompareToSystem.ValueTuple2101         int IStructuralComparable.CompareTo(object other, IComparer comparer)
2102         {
2103             if (other == null) return 1;
2104 
2105             if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>))
2106             {
2107                 throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, this.GetType().ToString()), nameof(other));
2108             }
2109 
2110             var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)other;
2111 
2112             int c = comparer.Compare(Item1, objTuple.Item1);
2113             if (c != 0) return c;
2114 
2115             c = comparer.Compare(Item2, objTuple.Item2);
2116             if (c != 0) return c;
2117 
2118             c = comparer.Compare(Item3, objTuple.Item3);
2119             if (c != 0) return c;
2120 
2121             c = comparer.Compare(Item4, objTuple.Item4);
2122             if (c != 0) return c;
2123 
2124             c = comparer.Compare(Item5, objTuple.Item5);
2125             if (c != 0) return c;
2126 
2127             c = comparer.Compare(Item6, objTuple.Item6);
2128             if (c != 0) return c;
2129 
2130             c = comparer.Compare(Item7, objTuple.Item7);
2131             if (c != 0) return c;
2132 
2133             return comparer.Compare(Rest, objTuple.Rest);
2134         }
2135 
2136         /// <summary>
2137         /// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.
2138         /// </summary>
2139         /// <returns>A 32-bit signed integer hash code.</returns>
GetHashCodeSystem.ValueTuple2140         public override int GetHashCode()
2141         {
2142             // We want to have a limited hash in this case.  We'll use the last 8 elements of the tuple
2143             IValueTupleInternal rest = Rest as IValueTupleInternal;
2144             if (rest == null)
2145             {
2146                 return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
2147                                                    Item2?.GetHashCode() ?? 0,
2148                                                    Item3?.GetHashCode() ?? 0,
2149                                                    Item4?.GetHashCode() ?? 0,
2150                                                    Item5?.GetHashCode() ?? 0,
2151                                                    Item6?.GetHashCode() ?? 0,
2152                                                    Item7?.GetHashCode() ?? 0);
2153             }
2154 
2155             int size = rest.Length;
2156             if (size >= 8) { return rest.GetHashCode(); }
2157 
2158             // In this case, the rest member has less than 8 elements so we need to combine some our elements with the elements in rest
2159             int k = 8 - size;
2160             switch (k)
2161             {
2162                 case 1:
2163                     return ValueTuple.CombineHashCodes(Item7?.GetHashCode() ?? 0,
2164                                                        rest.GetHashCode());
2165                 case 2:
2166                     return ValueTuple.CombineHashCodes(Item6?.GetHashCode() ?? 0,
2167                                                        Item7?.GetHashCode() ?? 0,
2168                                                        rest.GetHashCode());
2169                 case 3:
2170                     return ValueTuple.CombineHashCodes(Item5?.GetHashCode() ?? 0,
2171                                                        Item6?.GetHashCode() ?? 0,
2172                                                        Item7?.GetHashCode() ?? 0,
2173                                                        rest.GetHashCode());
2174                 case 4:
2175                     return ValueTuple.CombineHashCodes(Item4?.GetHashCode() ?? 0,
2176                                                        Item5?.GetHashCode() ?? 0,
2177                                                        Item6?.GetHashCode() ?? 0,
2178                                                        Item7?.GetHashCode() ?? 0,
2179                                                        rest.GetHashCode());
2180                 case 5:
2181                     return ValueTuple.CombineHashCodes(Item3?.GetHashCode() ?? 0,
2182                                                        Item4?.GetHashCode() ?? 0,
2183                                                        Item5?.GetHashCode() ?? 0,
2184                                                        Item6?.GetHashCode() ?? 0,
2185                                                        Item7?.GetHashCode() ?? 0,
2186                                                        rest.GetHashCode());
2187                 case 6:
2188                     return ValueTuple.CombineHashCodes(Item2?.GetHashCode() ?? 0,
2189                                                        Item3?.GetHashCode() ?? 0,
2190                                                        Item4?.GetHashCode() ?? 0,
2191                                                        Item5?.GetHashCode() ?? 0,
2192                                                        Item6?.GetHashCode() ?? 0,
2193                                                        Item7?.GetHashCode() ?? 0,
2194                                                        rest.GetHashCode());
2195                 case 7:
2196                 case 8:
2197                     return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0,
2198                                                        Item2?.GetHashCode() ?? 0,
2199                                                        Item3?.GetHashCode() ?? 0,
2200                                                        Item4?.GetHashCode() ?? 0,
2201                                                        Item5?.GetHashCode() ?? 0,
2202                                                        Item6?.GetHashCode() ?? 0,
2203                                                        Item7?.GetHashCode() ?? 0,
2204                                                        rest.GetHashCode());
2205             }
2206 
2207 #if !MONO
2208             Debug.Fail("Missed all cases for computing ValueTuple hash code");
2209 #endif
2210             return -1;
2211         }
2212 
IStructuralEquatable.GetHashCodeSystem.ValueTuple2213         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
2214         {
2215             return GetHashCodeCore(comparer);
2216         }
2217 
GetHashCodeCoreSystem.ValueTuple2218         private int GetHashCodeCore(IEqualityComparer comparer)
2219         {
2220             // We want to have a limited hash in this case.  We'll use the last 8 elements of the tuple
2221             IValueTupleInternal rest = Rest as IValueTupleInternal;
2222             if (rest == null)
2223             {
2224                 return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3),
2225                                                    comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6),
2226                                                    comparer.GetHashCode(Item7));
2227             }
2228 
2229             int size = rest.Length;
2230             if (size >= 8) { return rest.GetHashCode(comparer); }
2231 
2232             // In this case, the rest member has less than 8 elements so we need to combine some our elements with the elements in rest
2233             int k = 8 - size;
2234             switch (k)
2235             {
2236                 case 1:
2237                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
2238                 case 2:
2239                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
2240                 case 3:
2241                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7),
2242                                                        rest.GetHashCode(comparer));
2243                 case 4:
2244                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6),
2245                                                        comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
2246                 case 5:
2247                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item3), comparer.GetHashCode(Item4), comparer.GetHashCode(Item5),
2248                                                        comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
2249                 case 6:
2250                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), comparer.GetHashCode(Item4),
2251                                                        comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7),
2252                                                        rest.GetHashCode(comparer));
2253                 case 7:
2254                 case 8:
2255                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3),
2256                                                        comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6),
2257                                                        comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
2258             }
2259 
2260 #if !MONO
2261             Debug.Fail("Missed all cases for computing ValueTuple hash code");
2262 #endif
2263             return -1;
2264         }
2265 
IValueTupleInternal.GetHashCodeSystem.ValueTuple2266         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
2267         {
2268             return GetHashCodeCore(comparer);
2269         }
2270 
2271         /// <summary>
2272         /// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.
2273         /// </summary>
2274         /// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.</returns>
2275         /// <remarks>
2276         /// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7, Rest)</c>.
2277         /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
2278         /// </remarks>
ToStringSystem.ValueTuple2279         public override string ToString()
2280         {
2281             IValueTupleInternal rest = Rest as IValueTupleInternal;
2282             if (rest == null)
2283             {
2284                 return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")";
2285             }
2286             else
2287             {
2288                 return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + rest.ToStringEnd();
2289             }
2290         }
2291 
IValueTupleInternal.ToStringEndSystem.ValueTuple2292         string IValueTupleInternal.ToStringEnd()
2293         {
2294             IValueTupleInternal rest = Rest as IValueTupleInternal;
2295             if (rest == null)
2296             {
2297                 return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")";
2298             }
2299             else
2300             {
2301                 return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + rest.ToStringEnd();
2302             }
2303         }
2304 
2305         /// <summary>
2306         /// The number of positions in this data structure.
2307         /// </summary>
2308         int ITuple.Length
2309         {
2310             get
2311             {
2312                 IValueTupleInternal rest = Rest as IValueTupleInternal;
2313                 return rest == null ? 8 : 7 + rest.Length;
2314             }
2315         }
2316 
2317         /// <summary>
2318         /// Get the element at position <param name="index"/>.
2319         /// </summary>
2320         object ITuple.this[int index]
2321         {
2322             get
2323             {
2324                 switch (index)
2325                 {
2326                     case 0:
2327                         return Item1;
2328                     case 1:
2329                         return Item2;
2330                     case 2:
2331                         return Item3;
2332                     case 3:
2333                         return Item4;
2334                     case 4:
2335                         return Item5;
2336                     case 5:
2337                         return Item6;
2338                     case 6:
2339                         return Item7;
2340                 }
2341 
2342                 IValueTupleInternal rest = Rest as IValueTupleInternal;
2343                 if (rest == null)
2344                 {
2345                     if (index == 7)
2346                     {
2347                         return Rest;
2348                     }
2349                     throw new IndexOutOfRangeException();
2350                 }
2351                 return rest[index - 7];
2352             }
2353         }
2354     }
2355 }
2356