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