Pat Tullmann 0cb742dafb binfmt-detector-cli: rewrite to support PE32+ binaries (#38)
Rewrite with hard-coded offsets into the PE file format to discern
if a binary is PE32 or PE32+, and then to determine if it contains
a "CLR Data Directory" entry that looks valid.

Tested with PE32 and PE32+ compiled Mono binaries, PE32 and PE32+ native
binaries, and a random assortment of garbage files.

Former-commit-id: 9e7ac86ec84f653a2f79b87183efd5b0ebda001b
2023-10-16 20:16:47 +02:00

2079 lines
102 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace System
{
static class SR
{
public const string ArgumentException_ValueTupleIncorrectType = "ValueTupleIncorrectType";
public const string ArgumentException_ValueTupleLastArgumentNotAValueTuple = "ValueTupleLastArgumentNotAValueTuple";
}
/// <summary>
/// Helper so we can call some tuple methods recursively without knowing the underlying types.
/// </summary>
internal interface ITupleInternal
{
int GetHashCode(IEqualityComparer comparer);
int Size { get; }
string ToStringEnd();
}
/// <summary>
/// The ValueTuple types (from arity 0 to 8) comprise the runtime implementation that underlies tuples in C# and struct tuples in F#.
/// Aside from created via language syntax, they are most easily created via the ValueTuple.Create factory methods.
/// The System.ValueTuple types differ from the System.Tuple types in that:
/// - they are structs rather than classes,
/// - they are mutable rather than readonly, and
/// - their members (such as Item1, Item2, etc) are fields rather than properties.
/// </summary>
public struct ValueTuple
: IEquatable<ValueTuple>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple>, ITupleInternal
{
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple"/> instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if <paramref name="obj"/> is a <see cref="ValueTuple"/>.</returns>
public override bool Equals(object obj)
{
return obj is ValueTuple;
}
/// <summary>Returns a value indicating whether this instance is equal to a specified value.</summary>
/// <param name="other">An instance to compare to this instance.</param>
/// <returns>true if <paramref name="other"/> has the same value as this instance; otherwise, false.</returns>
public bool Equals(ValueTuple other)
{
return true;
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
return other is ValueTuple;
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return 0;
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple other)
{
return 0;
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return 0;
}
/// <summary>Returns the hash code for this instance.</summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return 0;
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return 0;
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return 0;
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>()</c>.
/// </remarks>
public override string ToString()
{
return "()";
}
string ITupleInternal.ToStringEnd()
{
return ")";
}
int ITupleInternal.Size => 0;
/// <summary>Creates a new struct 0-tuple.</summary>
/// <returns>A 0-tuple.</returns>
public static ValueTuple Create() =>
new ValueTuple();
/// <summary>Creates a new struct 1-tuple, or singleton.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <returns>A 1-tuple (singleton) whose value is (item1).</returns>
public static ValueTuple<T1> Create<T1>(T1 item1) =>
new ValueTuple<T1>(item1);
/// <summary>Creates a new struct 2-tuple, or pair.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <param name="item2">The value of the second component of the tuple.</param>
/// <returns>A 2-tuple (pair) whose value is (item1, item2).</returns>
public static ValueTuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) =>
new ValueTuple<T1, T2>(item1, item2);
/// <summary>Creates a new struct 3-tuple, or triple.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
/// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <param name="item2">The value of the second component of the tuple.</param>
/// <param name="item3">The value of the third component of the tuple.</param>
/// <returns>A 3-tuple (triple) whose value is (item1, item2, item3).</returns>
public static ValueTuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3) =>
new ValueTuple<T1, T2, T3>(item1, item2, item3);
/// <summary>Creates a new struct 4-tuple, or quadruple.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
/// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
/// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <param name="item2">The value of the second component of the tuple.</param>
/// <param name="item3">The value of the third component of the tuple.</param>
/// <param name="item4">The value of the fourth component of the tuple.</param>
/// <returns>A 4-tuple (quadruple) whose value is (item1, item2, item3, item4).</returns>
public static ValueTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4) =>
new ValueTuple<T1, T2, T3, T4>(item1, item2, item3, item4);
/// <summary>Creates a new struct 5-tuple, or quintuple.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
/// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
/// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
/// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <param name="item2">The value of the second component of the tuple.</param>
/// <param name="item3">The value of the third component of the tuple.</param>
/// <param name="item4">The value of the fourth component of the tuple.</param>
/// <param name="item5">The value of the fifth component of the tuple.</param>
/// <returns>A 5-tuple (quintuple) whose value is (item1, item2, item3, item4, item5).</returns>
public static ValueTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) =>
new ValueTuple<T1, T2, T3, T4, T5>(item1, item2, item3, item4, item5);
/// <summary>Creates a new struct 6-tuple, or sextuple.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
/// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
/// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
/// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
/// <typeparam name="T6">The type of the sixth component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <param name="item2">The value of the second component of the tuple.</param>
/// <param name="item3">The value of the third component of the tuple.</param>
/// <param name="item4">The value of the fourth component of the tuple.</param>
/// <param name="item5">The value of the fifth component of the tuple.</param>
/// <param name="item6">The value of the sixth component of the tuple.</param>
/// <returns>A 6-tuple (sextuple) whose value is (item1, item2, item3, item4, item5, item6).</returns>
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) =>
new ValueTuple<T1, T2, T3, T4, T5, T6>(item1, item2, item3, item4, item5, item6);
/// <summary>Creates a new struct 7-tuple, or septuple.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
/// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
/// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
/// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
/// <typeparam name="T6">The type of the sixth component of the tuple.</typeparam>
/// <typeparam name="T7">The type of the seventh component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <param name="item2">The value of the second component of the tuple.</param>
/// <param name="item3">The value of the third component of the tuple.</param>
/// <param name="item4">The value of the fourth component of the tuple.</param>
/// <param name="item5">The value of the fifth component of the tuple.</param>
/// <param name="item6">The value of the sixth component of the tuple.</param>
/// <param name="item7">The value of the seventh component of the tuple.</param>
/// <returns>A 7-tuple (septuple) whose value is (item1, item2, item3, item4, item5, item6, item7).</returns>
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) =>
new ValueTuple<T1, T2, T3, T4, T5, T6, T7>(item1, item2, item3, item4, item5, item6, item7);
/// <summary>Creates a new struct 8-tuple, or octuple.</summary>
/// <typeparam name="T1">The type of the first component of the tuple.</typeparam>
/// <typeparam name="T2">The type of the second component of the tuple.</typeparam>
/// <typeparam name="T3">The type of the third component of the tuple.</typeparam>
/// <typeparam name="T4">The type of the fourth component of the tuple.</typeparam>
/// <typeparam name="T5">The type of the fifth component of the tuple.</typeparam>
/// <typeparam name="T6">The type of the sixth component of the tuple.</typeparam>
/// <typeparam name="T7">The type of the seventh component of the tuple.</typeparam>
/// <typeparam name="T8">The type of the eigth component of the tuple.</typeparam>
/// <param name="item1">The value of the first component of the tuple.</param>
/// <param name="item2">The value of the second component of the tuple.</param>
/// <param name="item3">The value of the third component of the tuple.</param>
/// <param name="item4">The value of the fourth component of the tuple.</param>
/// <param name="item5">The value of the fifth component of the tuple.</param>
/// <param name="item6">The value of the sixth component of the tuple.</param>
/// <param name="item7">The value of the seventh component of the tuple.</param>
/// <param name="item8">The value of the eighth component of the tuple.</param>
/// <returns>An 8-tuple (octuple) whose value is (item1, item2, item3, item4, item5, item6, item7, item8).</returns>
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) =>
new ValueTuple<T1, T2, T3, T4, T5, T6, T7, ValueTuple<T8>>(item1, item2, item3, item4, item5, item6, item7, ValueTuple.Create(item8));
// From System.Web.Util.HashCodeCombiner
internal static int CombineHashCodes(int h1, int h2)
{
return (((h1 << 5) + h1) ^ h2);
}
internal static int CombineHashCodes(int h1, int h2, int h3)
{
return CombineHashCodes(CombineHashCodes(h1, h2), h3);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4)
{
return CombineHashCodes(CombineHashCodes(h1, h2), CombineHashCodes(h3, h4));
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5)
{
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), h5);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6)
{
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6));
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7)
{
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7));
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8)
{
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7, h8));
}
}
/// <summary>Represents a 1-tuple, or singleton, as a value type.</summary>
/// <typeparam name="T1">The type of the tuple's only component.</typeparam>
public struct ValueTuple<T1>
: IEquatable<ValueTuple<T1>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1>>, ITupleInternal
{
/// <summary>
/// The current <see cref="ValueTuple{T1}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
public ValueTuple(T1 item1)
{
Item1 = item1;
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1}"/> instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1> && Equals((ValueTuple<T1>)obj);
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1}"/>
/// instance is equal to a specified <see cref="ValueTuple{T1}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its field
/// is equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1);
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1>)) return false;
var objTuple = (ValueTuple<T1>)other;
return comparer.Equals(Item1, objTuple.Item1);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1>)other;
return Comparer<T1>.Default.Compare(Item1, objTuple.Item1);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1> other)
{
return Comparer<T1>.Default.Compare(Item1, other.Item1);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1>)other;
return comparer.Compare(Item1, objTuple.Item1);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return EqualityComparer<T1>.Default.GetHashCode(Item1);
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return comparer.GetHashCode(Item1);
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return comparer.GetHashCode(Item1);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1)</c>,
/// where <c>Item1</c> represents the value of <see cref="Item1"/>. If the field is <see langword="null"/>,
/// it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
return "(" + Item1?.ToString() + ")";
}
string ITupleInternal.ToStringEnd()
{
return Item1?.ToString() + ")";
}
int ITupleInternal.Size => 1;
}
/// <summary>
/// Represents a 2-tuple, or pair, as a value type.
/// </summary>
/// <typeparam name="T1">The type of the tuple's first component.</typeparam>
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
public struct ValueTuple<T1, T2>
: IEquatable<ValueTuple<T1, T2>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2>>, ITupleInternal
{
/// <summary>
/// The current <see cref="ValueTuple{T1, T2}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2}"/> instance's first component.
/// </summary>
public T2 Item2;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1, T2}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
/// <param name="item2">The value of the tuple's second component.</param>
public ValueTuple(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2}"/> instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
///
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1, T2}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1, T2> && Equals((ValueTuple<T1, T2>)obj);
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2}"/> instance is equal to a specified <see cref="ValueTuple{T1, T2}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
/// are equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1, T2> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
&& EqualityComparer<T2>.Default.Equals(Item2, other.Item2);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="other">The object to compare with this instance.</param>
/// <param name="comparer">An object that defines the method to use to evaluate whether the two objects are equal.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
///
/// <remarks>
/// This member is an explicit interface member implementation. It can be used only when the
/// <see cref="ValueTuple{T1, T2}"/> instance is cast to an <see cref="IStructuralEquatable"/> interface.
///
/// The <see cref="IEqualityComparer.Equals"/> implementation is called only if <c>other</c> is not <see langword="null"/>,
/// and if it can be successfully cast (in C#) or converted (in Visual Basic) to a <see cref="ValueTuple{T1, T2}"/>
/// whose components are of the same types as those of the current instance. The IStructuralEquatable.Equals(Object, IEqualityComparer) method
/// first passes the <see cref="Item1"/> values of the <see cref="ValueTuple{T1, T2}"/> objects to be compared to the
/// <see cref="IEqualityComparer.Equals"/> implementation. If this method call returns <see langword="true"/>, the method is
/// called again and passed the <see cref="Item2"/> values of the two <see cref="ValueTuple{T1, T2}"/> instances.
/// </remarks>
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1, T2>)) return false;
var objTuple = (ValueTuple<T1, T2>)other;
return comparer.Equals(Item1, objTuple.Item1)
&& comparer.Equals(Item2, objTuple.Item2);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return CompareTo((ValueTuple<T1, T2>)other);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2> other)
{
int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
if (c != 0) return c;
return Comparer<T2>.Default.Compare(Item2, other.Item2);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1, T2>)other;
int c = comparer.Compare(Item1, objTuple.Item1);
if (c != 0) return c;
return comparer.Compare(Item2, objTuple.Item2);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1, T2}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2));
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
private int GetHashCodeCore(IEqualityComparer comparer)
{
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
comparer.GetHashCode(Item2));
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2)</c>,
/// where <c>Item1</c> and <c>Item2</c> represent the values of the <see cref="Item1"/>
/// and <see cref="Item2"/> fields. If either field value is <see langword="null"/>,
/// it is represented as <see cref="String.Empty"/>.
/// </remarks>
public override string ToString()
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ")";
}
string ITupleInternal.ToStringEnd()
{
return Item1?.ToString() + ", " + Item2?.ToString() + ")";
}
int ITupleInternal.Size => 2;
}
/// <summary>
/// Represents a 3-tuple, or triple, as a value type.
/// </summary>
/// <typeparam name="T1">The type of the tuple's first component.</typeparam>
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
public struct ValueTuple<T1, T2, T3>
: IEquatable<ValueTuple<T1, T2, T3>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3>>, ITupleInternal
{
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3}"/> instance's second component.
/// </summary>
public T2 Item2;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3}"/> instance's third component.
/// </summary>
public T3 Item3;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
/// <param name="item2">The value of the tuple's second component.</param>
/// <param name="item3">The value of the tuple's third component.</param>
public ValueTuple(T1 item1, T2 item2, T3 item3)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3}"/> instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1, T2, T3}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1, T2, T3> && Equals((ValueTuple<T1, T2, T3>)obj);
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3}"/>
/// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
/// are equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1, T2, T3> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
&& EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
&& EqualityComparer<T3>.Default.Equals(Item3, other.Item3);
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1, T2, T3>)) return false;
var objTuple = (ValueTuple<T1, T2, T3>)other;
return comparer.Equals(Item1, objTuple.Item1)
&& comparer.Equals(Item2, objTuple.Item2)
&& comparer.Equals(Item3, objTuple.Item3);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return CompareTo((ValueTuple<T1, T2, T3>)other);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3> other)
{
int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
if (c != 0) return c;
c = Comparer<T2>.Default.Compare(Item2, other.Item2);
if (c != 0) return c;
return Comparer<T3>.Default.Compare(Item3, other.Item3);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1, T2, T3>)other;
int c = comparer.Compare(Item1, objTuple.Item1);
if (c != 0) return c;
c = comparer.Compare(Item2, objTuple.Item2);
if (c != 0) return c;
return comparer.Compare(Item3, objTuple.Item3);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3));
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
private int GetHashCodeCore(IEqualityComparer comparer)
{
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
comparer.GetHashCode(Item2),
comparer.GetHashCode(Item3));
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3)</c>.
/// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
/// </remarks>
public override string ToString()
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")";
}
string ITupleInternal.ToStringEnd()
{
return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ")";
}
int ITupleInternal.Size => 3;
}
/// <summary>
/// Represents a 4-tuple, or quadruple, as a value type.
/// </summary>
/// <typeparam name="T1">The type of the tuple's first component.</typeparam>
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
public struct ValueTuple<T1, T2, T3, T4>
: IEquatable<ValueTuple<T1, T2, T3, T4>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4>>, ITupleInternal
{
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's second component.
/// </summary>
public T2 Item2;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's third component.
/// </summary>
public T3 Item3;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance's fourth component.
/// </summary>
public T4 Item4;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
/// <param name="item2">The value of the tuple's second component.</param>
/// <param name="item3">The value of the tuple's third component.</param>
/// <param name="item4">The value of the tuple's fourth component.</param>
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
Item4 = item4;
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1, T2, T3, T4> && Equals((ValueTuple<T1, T2, T3, T4>)obj);
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4}"/>
/// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
/// are equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1, T2, T3, T4> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
&& EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
&& EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
&& EqualityComparer<T4>.Default.Equals(Item4, other.Item4);
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1, T2, T3, T4>)) return false;
var objTuple = (ValueTuple<T1, T2, T3, T4>)other;
return comparer.Equals(Item1, objTuple.Item1)
&& comparer.Equals(Item2, objTuple.Item2)
&& comparer.Equals(Item3, objTuple.Item3)
&& comparer.Equals(Item4, objTuple.Item4);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return CompareTo((ValueTuple<T1, T2, T3, T4>)other);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4> other)
{
int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
if (c != 0) return c;
c = Comparer<T2>.Default.Compare(Item2, other.Item2);
if (c != 0) return c;
c = Comparer<T3>.Default.Compare(Item3, other.Item3);
if (c != 0) return c;
return Comparer<T4>.Default.Compare(Item4, other.Item4);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1, T2, T3, T4>)other;
int c = comparer.Compare(Item1, objTuple.Item1);
if (c != 0) return c;
c = comparer.Compare(Item2, objTuple.Item2);
if (c != 0) return c;
c = comparer.Compare(Item3, objTuple.Item3);
if (c != 0) return c;
return comparer.Compare(Item4, objTuple.Item4);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4));
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
private int GetHashCodeCore(IEqualityComparer comparer)
{
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
comparer.GetHashCode(Item2),
comparer.GetHashCode(Item3),
comparer.GetHashCode(Item4));
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4)</c>.
/// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
/// </remarks>
public override string ToString()
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")";
}
string ITupleInternal.ToStringEnd()
{
return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ")";
}
int ITupleInternal.Size => 4;
}
/// <summary>
/// Represents a 5-tuple, or quintuple, as a value type.
/// </summary>
/// <typeparam name="T1">The type of the tuple's first component.</typeparam>
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
/// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
public struct ValueTuple<T1, T2, T3, T4, T5>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5>>, ITupleInternal
{
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's second component.
/// </summary>
public T2 Item2;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's third component.
/// </summary>
public T3 Item3;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's fourth component.
/// </summary>
public T4 Item4;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance's fifth component.
/// </summary>
public T5 Item5;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
/// <param name="item2">The value of the tuple's second component.</param>
/// <param name="item3">The value of the tuple's third component.</param>
/// <param name="item4">The value of the tuple's fourth component.</param>
/// <param name="item5">The value of the tuple's fifth component.</param>
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
Item4 = item4;
Item5 = item5;
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1, T2, T3, T4, T5> && Equals((ValueTuple<T1, T2, T3, T4, T5>)obj);
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/>
/// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4, T5}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
/// are equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1, T2, T3, T4, T5> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
&& EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
&& EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
&& EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
&& EqualityComparer<T5>.Default.Equals(Item5, other.Item5);
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5>)) return false;
var objTuple = (ValueTuple<T1, T2, T3, T4, T5>)other;
return comparer.Equals(Item1, objTuple.Item1)
&& comparer.Equals(Item2, objTuple.Item2)
&& comparer.Equals(Item3, objTuple.Item3)
&& comparer.Equals(Item4, objTuple.Item4)
&& comparer.Equals(Item5, objTuple.Item5);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return CompareTo((ValueTuple<T1, T2, T3, T4, T5>)other);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5> other)
{
int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
if (c != 0) return c;
c = Comparer<T2>.Default.Compare(Item2, other.Item2);
if (c != 0) return c;
c = Comparer<T3>.Default.Compare(Item3, other.Item3);
if (c != 0) return c;
c = Comparer<T4>.Default.Compare(Item4, other.Item4);
if (c != 0) return c;
return Comparer<T5>.Default.Compare(Item5, other.Item5);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1, T2, T3, T4, T5>)other;
int c = comparer.Compare(Item1, objTuple.Item1);
if (c != 0) return c;
c = comparer.Compare(Item2, objTuple.Item2);
if (c != 0) return c;
c = comparer.Compare(Item3, objTuple.Item3);
if (c != 0) return c;
c = comparer.Compare(Item4, objTuple.Item4);
if (c != 0) return c;
return comparer.Compare(Item5, objTuple.Item5);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5));
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
private int GetHashCodeCore(IEqualityComparer comparer)
{
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
comparer.GetHashCode(Item2),
comparer.GetHashCode(Item3),
comparer.GetHashCode(Item4),
comparer.GetHashCode(Item5));
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5)</c>.
/// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
/// </remarks>
public override string ToString()
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")";
}
string ITupleInternal.ToStringEnd()
{
return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ")";
}
int ITupleInternal.Size => 5;
}
/// <summary>
/// Represents a 6-tuple, or sixtuple, as a value type.
/// </summary>
/// <typeparam name="T1">The type of the tuple's first component.</typeparam>
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
/// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
/// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
public struct ValueTuple<T1, T2, T3, T4, T5, T6>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6>>, ITupleInternal
{
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's second component.
/// </summary>
public T2 Item2;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's third component.
/// </summary>
public T3 Item3;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's fourth component.
/// </summary>
public T4 Item4;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's fifth component.
/// </summary>
public T5 Item5;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance's sixth component.
/// </summary>
public T6 Item6;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
/// <param name="item2">The value of the tuple's second component.</param>
/// <param name="item3">The value of the tuple's third component.</param>
/// <param name="item4">The value of the tuple's fourth component.</param>
/// <param name="item5">The value of the tuple's fifth component.</param>
/// <param name="item6">The value of the tuple's sixth component.</param>
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
Item4 = item4;
Item5 = item5;
Item6 = item6;
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1, T2, T3, T4, T5, T6> && Equals((ValueTuple<T1, T2, T3, T4, T5, T6>)obj);
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/>
/// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
/// are equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1, T2, T3, T4, T5, T6> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
&& EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
&& EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
&& EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
&& EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
&& EqualityComparer<T6>.Default.Equals(Item6, other.Item6);
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5, T6>)) return false;
var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6>)other;
return comparer.Equals(Item1, objTuple.Item1)
&& comparer.Equals(Item2, objTuple.Item2)
&& comparer.Equals(Item3, objTuple.Item3)
&& comparer.Equals(Item4, objTuple.Item4)
&& comparer.Equals(Item5, objTuple.Item5)
&& comparer.Equals(Item6, objTuple.Item6);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return CompareTo((ValueTuple<T1, T2, T3, T4, T5, T6>)other);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6> other)
{
int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
if (c != 0) return c;
c = Comparer<T2>.Default.Compare(Item2, other.Item2);
if (c != 0) return c;
c = Comparer<T3>.Default.Compare(Item3, other.Item3);
if (c != 0) return c;
c = Comparer<T4>.Default.Compare(Item4, other.Item4);
if (c != 0) return c;
c = Comparer<T5>.Default.Compare(Item5, other.Item5);
if (c != 0) return c;
return Comparer<T6>.Default.Compare(Item6, other.Item6);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6>)other;
int c = comparer.Compare(Item1, objTuple.Item1);
if (c != 0) return c;
c = comparer.Compare(Item2, objTuple.Item2);
if (c != 0) return c;
c = comparer.Compare(Item3, objTuple.Item3);
if (c != 0) return c;
c = comparer.Compare(Item4, objTuple.Item4);
if (c != 0) return c;
c = comparer.Compare(Item5, objTuple.Item5);
if (c != 0) return c;
return comparer.Compare(Item6, objTuple.Item6);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6));
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
private int GetHashCodeCore(IEqualityComparer comparer)
{
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
comparer.GetHashCode(Item2),
comparer.GetHashCode(Item3),
comparer.GetHashCode(Item4),
comparer.GetHashCode(Item5),
comparer.GetHashCode(Item6));
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6)</c>.
/// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
/// </remarks>
public override string ToString()
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")";
}
string ITupleInternal.ToStringEnd()
{
return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ")";
}
int ITupleInternal.Size => 6;
}
/// <summary>
/// Represents a 7-tuple, or sentuple, as a value type.
/// </summary>
/// <typeparam name="T1">The type of the tuple's first component.</typeparam>
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
/// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
/// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
/// <typeparam name="T7">The type of the tuple's seventh component.</typeparam>
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, ITupleInternal
{
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's second component.
/// </summary>
public T2 Item2;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's third component.
/// </summary>
public T3 Item3;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's fourth component.
/// </summary>
public T4 Item4;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's fifth component.
/// </summary>
public T5 Item5;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's sixth component.
/// </summary>
public T6 Item6;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance's seventh component.
/// </summary>
public T7 Item7;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
/// <param name="item2">The value of the tuple's second component.</param>
/// <param name="item3">The value of the tuple's third component.</param>
/// <param name="item4">The value of the tuple's fourth component.</param>
/// <param name="item5">The value of the tuple's fifth component.</param>
/// <param name="item6">The value of the tuple's sixth component.</param>
/// <param name="item7">The value of the tuple's seventh component.</param>
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
Item4 = item4;
Item5 = item5;
Item6 = item6;
Item7 = item7;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1, T2, T3, T4, T5, T6, T7> && Equals((ValueTuple<T1, T2, T3, T4, T5, T6, T7>)obj);
}
/// <summary>
/// Returns a value that indicates whether the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/>
/// instance is equal to a specified <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
/// are equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1, T2, T3, T4, T5, T6, T7> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
&& EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
&& EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
&& EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
&& EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
&& EqualityComparer<T6>.Default.Equals(Item6, other.Item6)
&& EqualityComparer<T7>.Default.Equals(Item7, other.Item7);
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7>)) return false;
var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7>)other;
return comparer.Equals(Item1, objTuple.Item1)
&& comparer.Equals(Item2, objTuple.Item2)
&& comparer.Equals(Item3, objTuple.Item3)
&& comparer.Equals(Item4, objTuple.Item4)
&& comparer.Equals(Item5, objTuple.Item5)
&& comparer.Equals(Item6, objTuple.Item6)
&& comparer.Equals(Item7, objTuple.Item7);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return CompareTo((ValueTuple<T1, T2, T3, T4, T5, T6, T7>)other);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6, T7> other)
{
int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
if (c != 0) return c;
c = Comparer<T2>.Default.Compare(Item2, other.Item2);
if (c != 0) return c;
c = Comparer<T3>.Default.Compare(Item3, other.Item3);
if (c != 0) return c;
c = Comparer<T4>.Default.Compare(Item4, other.Item4);
if (c != 0) return c;
c = Comparer<T5>.Default.Compare(Item5, other.Item5);
if (c != 0) return c;
c = Comparer<T6>.Default.Compare(Item6, other.Item6);
if (c != 0) return c;
return Comparer<T7>.Default.Compare(Item7, other.Item7);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7>)other;
int c = comparer.Compare(Item1, objTuple.Item1);
if (c != 0) return c;
c = comparer.Compare(Item2, objTuple.Item2);
if (c != 0) return c;
c = comparer.Compare(Item3, objTuple.Item3);
if (c != 0) return c;
c = comparer.Compare(Item4, objTuple.Item4);
if (c != 0) return c;
c = comparer.Compare(Item5, objTuple.Item5);
if (c != 0) return c;
c = comparer.Compare(Item6, objTuple.Item6);
if (c != 0) return c;
return comparer.Compare(Item7, objTuple.Item7);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7));
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
private int GetHashCodeCore(IEqualityComparer comparer)
{
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1),
comparer.GetHashCode(Item2),
comparer.GetHashCode(Item3),
comparer.GetHashCode(Item4),
comparer.GetHashCode(Item5),
comparer.GetHashCode(Item6),
comparer.GetHashCode(Item7));
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7)</c>.
/// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
/// </remarks>
public override string ToString()
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")";
}
string ITupleInternal.ToStringEnd()
{
return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ")";
}
int ITupleInternal.Size => 7;
}
/// <summary>
/// Represents an 8-tuple, or octuple, as a value type.
/// </summary>
/// <typeparam name="T1">The type of the tuple's first component.</typeparam>
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
/// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
/// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
/// <typeparam name="T7">The type of the tuple's seventh component.</typeparam>
/// <typeparam name="TRest">The type of the tuple's eigth component.</typeparam>
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, ITupleInternal
where TRest : struct
{
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's first component.
/// </summary>
public T1 Item1;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's second component.
/// </summary>
public T2 Item2;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's third component.
/// </summary>
public T3 Item3;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's fourth component.
/// </summary>
public T4 Item4;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's fifth component.
/// </summary>
public T5 Item5;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's sixth component.
/// </summary>
public T6 Item6;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's seventh component.
/// </summary>
public T7 Item7;
/// <summary>
/// The current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance's eigth component.
/// </summary>
public TRest Rest;
/// <summary>
/// Initializes a new instance of the <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> value type.
/// </summary>
/// <param name="item1">The value of the tuple's first component.</param>
/// <param name="item2">The value of the tuple's second component.</param>
/// <param name="item3">The value of the tuple's third component.</param>
/// <param name="item4">The value of the tuple's fourth component.</param>
/// <param name="item5">The value of the tuple's fifth component.</param>
/// <param name="item6">The value of the tuple's sixth component.</param>
/// <param name="item7">The value of the tuple's seventh component.</param>
/// <param name="rest">The value of the tuple's eight component.</param>
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest)
{
if (!(rest is ITupleInternal))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleLastArgumentNotAValueTuple);
}
Item1 = item1;
Item2 = item2;
Item3 = item3;
Item4 = item4;
Item5 = item5;
Item6 = item6;
Item7 = item7;
Rest = rest;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified object; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="obj"/> parameter is considered to be equal to the current instance under the following conditions:
/// <list type="bullet">
/// <item><description>It is a <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> value type.</description></item>
/// <item><description>Its components are of the same types as those of the current instance.</description></item>
/// <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>
/// </list>
/// </remarks>
public override bool Equals(object obj)
{
return obj is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> && Equals((ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)obj);
}
/// <summary>
/// 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 <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/>.
/// </summary>
/// <param name="other">The tuple to compare with this instance.</param>
/// <returns><see langword="true"/> if the current instance is equal to the specified tuple; otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// The <paramref name="other"/> parameter is considered to be equal to the current instance if each of its fields
/// are equal to that of the current instance, using the default comparer for that field's type.
/// </remarks>
public bool Equals(ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
&& EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
&& EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
&& EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
&& EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
&& EqualityComparer<T6>.Default.Equals(Item6, other.Item6)
&& EqualityComparer<T7>.Default.Equals(Item7, other.Item7)
&& EqualityComparer<TRest>.Default.Equals(Rest, other.Rest);
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null || !(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)) return false;
var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)other;
return comparer.Equals(Item1, objTuple.Item1)
&& comparer.Equals(Item2, objTuple.Item2)
&& comparer.Equals(Item3, objTuple.Item3)
&& comparer.Equals(Item4, objTuple.Item4)
&& comparer.Equals(Item5, objTuple.Item5)
&& comparer.Equals(Item6, objTuple.Item6)
&& comparer.Equals(Item7, objTuple.Item7)
&& comparer.Equals(Rest, objTuple.Rest);
}
int IComparable.CompareTo(object other)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
return CompareTo((ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)other);
}
/// <summary>Compares this instance to a specified instance and returns an indication of their relative values.</summary>
/// <param name="other">An instance to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
/// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other)
{
int c = Comparer<T1>.Default.Compare(Item1, other.Item1);
if (c != 0) return c;
c = Comparer<T2>.Default.Compare(Item2, other.Item2);
if (c != 0) return c;
c = Comparer<T3>.Default.Compare(Item3, other.Item3);
if (c != 0) return c;
c = Comparer<T4>.Default.Compare(Item4, other.Item4);
if (c != 0) return c;
c = Comparer<T5>.Default.Compare(Item5, other.Item5);
if (c != 0) return c;
c = Comparer<T6>.Default.Compare(Item6, other.Item6);
if (c != 0) return c;
c = Comparer<T7>.Default.Compare(Item7, other.Item7);
if (c != 0) return c;
return Comparer<TRest>.Default.Compare(Rest, other.Rest);
}
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
if (!(other is ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>))
{
throw new ArgumentException(SR.ArgumentException_ValueTupleIncorrectType, nameof(other));
}
var objTuple = (ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>)other;
int c = comparer.Compare(Item1, objTuple.Item1);
if (c != 0) return c;
c = comparer.Compare(Item2, objTuple.Item2);
if (c != 0) return c;
c = comparer.Compare(Item3, objTuple.Item3);
if (c != 0) return c;
c = comparer.Compare(Item4, objTuple.Item4);
if (c != 0) return c;
c = comparer.Compare(Item5, objTuple.Item5);
if (c != 0) return c;
c = comparer.Compare(Item6, objTuple.Item6);
if (c != 0) return c;
c = comparer.Compare(Item7, objTuple.Item7);
if (c != 0) return c;
return comparer.Compare(Rest, objTuple.Rest);
}
/// <summary>
/// Returns the hash code for the current <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
// We want to have a limited hash in this case. We'll use the last 8 elements of the tuple
ITupleInternal rest = Rest as ITupleInternal;
if (rest == null)
{
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7));
}
int size = rest.Size;
if (size >= 8) { return rest.GetHashCode(); }
// In this case, the rest member has less than 8 elements so we need to combine some our elements with the elements in rest
int k = 8 - size;
switch (k)
{
case 1:
return ValueTuple.CombineHashCodes(EqualityComparer<T7>.Default.GetHashCode(Item7),
rest.GetHashCode());
case 2:
return ValueTuple.CombineHashCodes(EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7),
rest.GetHashCode());
case 3:
return ValueTuple.CombineHashCodes(EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7),
rest.GetHashCode());
case 4:
return ValueTuple.CombineHashCodes(EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7),
rest.GetHashCode());
case 5:
return ValueTuple.CombineHashCodes(EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7),
rest.GetHashCode());
case 6:
return ValueTuple.CombineHashCodes(EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7),
rest.GetHashCode());
case 7:
case 8:
return ValueTuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
EqualityComparer<T2>.Default.GetHashCode(Item2),
EqualityComparer<T3>.Default.GetHashCode(Item3),
EqualityComparer<T4>.Default.GetHashCode(Item4),
EqualityComparer<T5>.Default.GetHashCode(Item5),
EqualityComparer<T6>.Default.GetHashCode(Item6),
EqualityComparer<T7>.Default.GetHashCode(Item7),
rest.GetHashCode());
}
// Debug.Assert(false, "Missed all cases for computing ValueTuple hash code");
return -1;
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
private int GetHashCodeCore(IEqualityComparer comparer)
{
// We want to have a limited hash in this case. We'll use the last 8 elements of the tuple
ITupleInternal rest = Rest as ITupleInternal;
if (rest == null)
{
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3),
comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6),
comparer.GetHashCode(Item7));
}
int size = rest.Size;
if (size >= 8) { return rest.GetHashCode(comparer); }
// In this case, the rest member has less than 8 elements so we need to combine some our elements with the elements in rest
int k = 8 - size;
switch (k)
{
case 1:
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
case 2:
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
case 3:
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7),
rest.GetHashCode(comparer));
case 4:
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6),
comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
case 5:
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item3), comparer.GetHashCode(Item4), comparer.GetHashCode(Item5),
comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
case 6:
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), comparer.GetHashCode(Item4),
comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7),
rest.GetHashCode(comparer));
case 7:
case 8:
return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3),
comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6),
comparer.GetHashCode(Item7), rest.GetHashCode(comparer));
}
// Debug.Assert(false, "Missed all cases for computing ValueTuple hash code");
return -1;
}
int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return GetHashCodeCore(comparer);
}
/// <summary>
/// Returns a string that represents the value of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.
/// </summary>
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7, Rest)</c>.
/// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
/// </remarks>
public override string ToString()
{
ITupleInternal rest = Rest as ITupleInternal;
if (rest == null)
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")";
}
else
{
return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + rest.ToStringEnd();
}
}
string ITupleInternal.ToStringEnd()
{
ITupleInternal rest = Rest as ITupleInternal;
if (rest == null)
{
return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")";
}
else
{
return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + rest.ToStringEnd();
}
}
int ITupleInternal.Size
{
get
{
ITupleInternal rest = Rest as ITupleInternal;
return rest == null ? 8 : 7 + rest.Size;
}
}
}
}