File: Pair.cs

package info (click to toggle)
quickroute-gps 2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 19,576 kB
  • sloc: cs: 74,488; makefile: 72; sh: 43
file content (242 lines) | stat: -rw-r--r-- 12,314 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
//******************************
// Written by Peter Golde
// Copyright (c) 2004-2007, Wintellect
//
// Use and restribution of this code is subject to the license agreement 
// contained in the file "License.txt" accompanying this file.
//******************************

using System;
using System.Collections.Generic;

namespace Wintellect.PowerCollections
{
    /// <summary>
    /// Stores a pair of objects within a single struct. This struct is useful to use as the
    /// T of a collection, or as the TKey or TValue of a dictionary.
    /// </summary>
    [Serializable]
    public struct Pair<TFirst, TSecond> : IComparable, IComparable<Pair<TFirst, TSecond>>
    {
        /// <summary>
        /// Comparers for the first and second type that are used to compare
        /// values.
        /// </summary>

        private static readonly IComparer<TFirst> firstComparer = Comparer<TFirst>.Default;
        private static readonly IComparer<TSecond> secondComparer = Comparer<TSecond>.Default;

        private static readonly IEqualityComparer<TFirst> firstEqualityComparer = EqualityComparer<TFirst>.Default;
        private static readonly IEqualityComparer<TSecond> secondEqualityComparer = EqualityComparer<TSecond>.Default;

        /// <summary>
        /// The first element of the pair.
        /// </summary>
        public TFirst First;

        /// <summary>
        /// The second element of the pair.
        /// </summary>
        public TSecond Second;

        /// <summary>
        /// Creates a new pair with given first and second elements.
        /// </summary>
        /// <param name="first">The first element of the pair.</param>
        /// <param name="second">The second element of the pair.</param>
        public Pair(TFirst first, TSecond second)
        {
            this.First = first;
            this.Second = second;
        }

        /// <summary>
        /// Creates a new pair using elements from a KeyValuePair structure. The
        /// First element gets the Key, and the Second elements gets the Value.
        /// </summary>
        /// <param name="keyAndValue">The KeyValuePair to initialize the Pair with .</param>
        public Pair(KeyValuePair<TFirst,TSecond> keyAndValue)
        {
            this.First = keyAndValue.Key;
            this.Second = keyAndValue.Value;
        }

        /// <summary>
        /// Determines if this pair is equal to another object. The pair is equal to another object 
        /// if that object is a Pair, both element types are the same, and the first and second elements
        /// both compare equal using object.Equals.
        /// </summary>
        /// <param name="obj">Object to compare for equality.</param>
        /// <returns>True if the objects are equal. False if the objects are not equal.</returns>
        public override bool Equals(object obj)
        {
            if (obj != null && obj is Pair<TFirst, TSecond>) {
                Pair<TFirst, TSecond> other = (Pair<TFirst, TSecond>)obj;

                return Equals(other);
            }
            else {
                return false;
            }
        }

        /// <summary>
        /// Determines if this pair is equal to another pair. The pair is equal if  the first and second elements
        /// both compare equal using IComparable&lt;T&gt;.Equals or object.Equals.
        /// </summary>
        /// <param name="other">Pair to compare with for equality.</param>
        /// <returns>True if the pairs are equal. False if the pairs are not equal.</returns>
        public bool Equals(Pair<TFirst, TSecond> other)
        {
            return firstEqualityComparer.Equals(First, other.First) && secondEqualityComparer.Equals(Second, other.Second);
        }

        /// <summary>
        /// Returns a hash code for the pair, suitable for use in a hash-table or other hashed collection.
        /// Two pairs that compare equal (using Equals) will have the same hash code. The hash code for
        /// the pair is derived by combining the hash codes for each of the two elements of the pair.
        /// </summary>
        /// <returns>The hash code.</returns>
        public override int GetHashCode()
        {
            // Build the hash code from the hash codes of First and Second. 
            int hashFirst = (First == null) ? 0x61E04917 : First.GetHashCode();
            int hashSecond = (Second == null) ? 0x198ED6A3 : Second.GetHashCode();
            return hashFirst ^ hashSecond;
        }

        /// <summary>
        /// <para> Compares this pair to another pair of the some type. The pairs are compared by using
        /// the IComparable&lt;T&gt; or IComparable interface on TFirst and TSecond. The pairs
        /// are compared by their first elements first, if their first elements are equal, then they
        /// are compared by their second elements.</para>
        /// <para>If either TFirst or TSecond does not implement IComparable&lt;T&gt; or IComparable, then
        /// an NotSupportedException is thrown, because the pairs cannot be compared.</para>
        /// </summary>
        /// <param name="other">The pair to compare to.</param>
        /// <returns>An integer indicating how this pair compares to <paramref name="other"/>. Less
        /// than zero indicates this pair is less than <paramref name="other"/>. Zero indicate this pair is
        /// equals to <paramref name="other"/>. Greater than zero indicates this pair is greater than
        /// <paramref name="other"/>.</returns>
        /// <exception cref="NotSupportedException">Either FirstSecond or TSecond is not comparable
        /// via the IComparable&lt;T&gt; or IComparable interfaces.</exception>
        public int CompareTo(Pair<TFirst, TSecond> other)
        {
            try {
                int firstCompare = firstComparer.Compare(First, other.First);
                if (firstCompare != 0)
                    return firstCompare;
                else
                    return secondComparer.Compare(Second, other.Second);
            }
            catch (ArgumentException) {
                // Determine which type caused the problem for a better error message.
                if (!typeof(IComparable<TFirst>).IsAssignableFrom(typeof(TFirst)) &&
                    !typeof(System.IComparable).IsAssignableFrom(typeof(TFirst))) {
                    throw new NotSupportedException(string.Format(Strings.UncomparableType, typeof(TFirst).FullName));
                }
                else if (!typeof(IComparable<TSecond>).IsAssignableFrom(typeof(TSecond)) &&
                    !typeof(System.IComparable).IsAssignableFrom(typeof(TSecond))) {
                    throw new NotSupportedException(string.Format(Strings.UncomparableType, typeof(TSecond).FullName));
                }
                else
                    throw;              // Hmmm. Unclear why we got the ArgumentException. 
            }
        }

        /// <summary>
        /// <para> Compares this pair to another pair of the some type. The pairs are compared by using
        /// the IComparable&lt;T&gt; or IComparable interface on TFirst and TSecond. The pairs
        /// are compared by their first elements first, if their first elements are equal, then they
        /// are compared by their second elements.</para>
        /// <para>If either TFirst or TSecond does not implement IComparable&lt;T&gt; or IComparable, then
        /// an NotSupportedException is thrown, because the pairs cannot be compared.</para>
        /// </summary>
        /// <param name="obj">The pair to compare to.</param>
        /// <returns>An integer indicating how this pair compares to <paramref name="obj"/>. Less
        /// than zero indicates this pair is less than <paramref name="obj"/>. Zero indicate this pair is
        /// equals to <paramref name="obj"/>. Greater than zero indicates this pair is greater than
        /// <paramref name="obj"/>.</returns>
        /// <exception cref="ArgumentException"><paramref name="obj"/> is not of the correct type.</exception>
        /// <exception cref="NotSupportedException">Either FirstSecond or TSecond is not comparable
        /// via the IComparable&lt;T&gt; or IComparable interfaces.</exception>
        int IComparable.CompareTo(object obj)
        {
            if (obj is Pair<TFirst, TSecond>)
                return CompareTo((Pair<TFirst, TSecond>)obj);
            else
                throw new ArgumentException(Strings.BadComparandType, "obj");
        }

        /// <summary>
        /// Returns a string representation of the pair. The string representation of the pair is
        /// of the form:
        /// <c>First: {0}, Second: {1}</c>
        /// where {0} is the result of First.ToString(), and {1} is the result of Second.ToString() (or
        /// "null" if they are null.)
        /// </summary>
        /// <returns> The string representation of the pair.</returns>
        public override string ToString()
        {
            return string.Format("First: {0}, Second: {1}", (First == null) ? "null" : First.ToString(), (Second == null) ? "null" : Second.ToString());
        }

        /// <summary>
        /// Determines if two pairs are equal. Two pairs are equal if  the first and second elements
        /// both compare equal using IComparable&lt;T&gt;.Equals or object.Equals.
        /// </summary>
        /// <param name="pair1">First pair to compare.</param>
        /// <param name="pair2">Second pair to compare.</param>
        /// <returns>True if the pairs are equal. False if the pairs are not equal.</returns>
        public static bool operator ==(Pair<TFirst, TSecond> pair1, Pair<TFirst, TSecond> pair2)
        {
            return firstEqualityComparer.Equals(pair1.First, pair2.First) && secondEqualityComparer.Equals(pair1.Second, pair2.Second);
        }

        /// <summary>
        /// Determines if two pairs are not equal. Two pairs are equal if  the first and second elements
        /// both compare equal using IComparable&lt;T&gt;.Equals or object.Equals.
        /// </summary>
        /// <param name="pair1">First pair to compare.</param>
        /// <param name="pair2">Second pair to compare.</param>
        /// <returns>True if the pairs are not equal. False if the pairs are equal.</returns>
        public static bool operator !=(Pair<TFirst, TSecond> pair1, Pair<TFirst, TSecond> pair2)
        {
            return !(pair1 == pair2);
        }

        /// <summary>
        /// Converts a Pair to a KeyValuePair. The Key part of the KeyValuePair gets
        /// the First element, and the Value part of the KeyValuePair gets the Second 
        /// elements.
        /// </summary>
        /// <param name="pair">Pair to convert.</param>
        /// <returns>The KeyValuePair created from <paramref name="pair"/>.</returns>
        public static explicit operator KeyValuePair<TFirst,TSecond>(Pair<TFirst, TSecond> pair)
        {
            return new KeyValuePair<TFirst, TSecond>(pair.First, pair.Second);
        }

        /// <summary>
        /// Converts this Pair to a KeyValuePair. The Key part of the KeyValuePair gets
        /// the First element, and the Value part of the KeyValuePair gets the Second 
        /// elements.
        /// </summary>
        /// <returns>The KeyValuePair created from this Pair.</returns>
        public KeyValuePair<TFirst, TSecond> ToKeyValuePair()
        {
            return new KeyValuePair<TFirst, TSecond>(this.First, this.Second);
        }

        /// <summary>
        /// Converts a KeyValuePair structure into a Pair. The
        /// First element gets the Key, and the Second element gets the Value.
        /// </summary>
        /// <param name="keyAndValue">The KeyValuePair to convert.</param>
        /// <returns>The Pair created by converted the KeyValuePair into a Pair.</returns>
        public static explicit operator Pair<TFirst, TSecond>(KeyValuePair<TFirst, TSecond> keyAndValue)
        {
            return new Pair<TFirst, TSecond>(keyAndValue);
        }
    }
}