Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
EquatableList.cs
Go to the documentation of this file.
1 /*
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements. See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership. The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License. You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied. See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20 */
21 
22 using System;
23 using System.Collections;
24 using System.Collections.Generic;
25 
26 namespace Lucene.Net.Support
27 {
33  [Serializable]
34  public class EquatableList<T> : System.Collections.Generic.List<T>,
35  IEquatable<System.Collections.Generic.IEnumerable<T>>,
36  ICloneable
37  {
41  public EquatableList() : base() { }
42 
47  public EquatableList(System.Collections.Generic.IEnumerable<T> collection) : base(collection) { }
48 
52  public EquatableList(int capacity) : base(capacity) { }
53 
58  public void AddRange(ICollection c)
59  {
60  // If the collection is null, throw an exception.
61  if (c == null) throw new ArgumentNullException("c");
62 
63  // Pre-compute capacity.
64  Capacity = Math.Max(c.Count + Count, Capacity);
65 
66  // Cycle through the items and add.
67  foreach (T item in c)
68  {
69  // Add the item.
70  Add(item);
71  }
72  }
73 
89  private static bool? EnumerableCountsEqual(System.Collections.Generic.IEnumerable<T> x, System.Collections.Generic.IEnumerable<T> y)
90  {
91  // Get the ICollection<T> and ICollection interfaces.
92  System.Collections.Generic.ICollection<T> xOfTCollection = x as System.Collections.Generic.ICollection<T>;
93  System.Collections.Generic.ICollection<T> yOfTCollection = y as System.Collections.Generic.ICollection<T>;
94  ICollection xCollection = x as ICollection;
95  ICollection yCollection = y as ICollection;
96 
97  // The count in x and y.
98  int? xCount = xOfTCollection != null ? xOfTCollection.Count : xCollection != null ? xCollection.Count : (int?)null;
99  int? yCount = yOfTCollection != null ? yOfTCollection.Count : yCollection != null ? yCollection.Count : (int?)null;
100 
101  // If either are null, return null, the result is indeterminate.
102  if (xCount == null || yCount == null)
103  {
104  // Return null, indeterminate.
105  return null;
106  }
107 
108  // Both counts are non-null, compare.
109  return xCount == yCount;
110  }
111 
125  private static bool Equals(System.Collections.Generic.IEnumerable<T> x,
126  System.Collections.Generic.IEnumerable<T> y)
127  {
128  // If x and y are null, then return true, they are the same.
129  if (x == null && y == null)
130  {
131  // They are the same, return 0.
132  return true;
133  }
134 
135  // If one is null, then return a value based on whether or not
136  // one is null or not.
137  if (x == null || y == null)
138  {
139  // Return false, one is null, the other is not.
140  return false;
141  }
142 
143  // Check to see if the counts on the IEnumerable implementations are equal.
144  // This is a shortcut, if they are not equal, then the lists are not equal.
145  // If the result is indeterminate, then get out.
146  bool? enumerableCountsEqual = EnumerableCountsEqual(x, y);
147 
148  // If the enumerable counts have been able to be calculated (indicated by
149  // a non-null value) and it is false, then no need to iterate through the items.
150  if (enumerableCountsEqual != null && !enumerableCountsEqual.Value)
151  {
152  // The sequences are not equal.
153  return false;
154  }
155 
156  // The counts of the items in the enumerations are equal, or indeterminate
157  // so a full iteration needs to be made to compare each item.
158  // Get the default comparer for T first.
159  System.Collections.Generic.EqualityComparer<T> defaultComparer =
160  EqualityComparer<T>.Default;
161 
162  // Get the enumerator for y.
163  System.Collections.Generic.IEnumerator<T> otherEnumerator = y.GetEnumerator();
164 
165  // Call Dispose on IDisposable if there is an implementation on the
166  // IEnumerator<T> returned by a call to y.GetEnumerator().
167  using (otherEnumerator as IDisposable)
168  {
169  // Cycle through the items in this list.
170  foreach (T item in x)
171  {
172  // If there isn't an item to get, then this has more
173  // items than that, they are not equal.
174  if (!otherEnumerator.MoveNext())
175  {
176  // Return false.
177  return false;
178  }
179 
180  // Perform a comparison. Must check this on the left hand side
181  // and that on the right hand side.
182  bool comparison = defaultComparer.Equals(item, otherEnumerator.Current);
183 
184  // If the value is false, return false.
185  if (!comparison)
186  {
187  // Return the value.
188  return comparison;
189  }
190  }
191 
192  // If there are no more items, then return true, the sequences
193  // are equal.
194  if (!otherEnumerator.MoveNext())
195  {
196  // The sequences are equal.
197  return true;
198  }
199 
200  // The other sequence has more items than this one, return
201  // false, these are not equal.
202  return false;
203  }
204  }
205 
206  #region IEquatable<IEnumerable<T>> Members
207 
208 
209 
210 
211 
212 
213  public bool Equals(System.Collections.Generic.IEnumerable<T> other)
214  {
215  // Compare to the other sequence. If 0, then equal.
216  return Equals(this, other);
217  }
218  #endregion
219 
224  public override bool Equals(object obj)
225  {
226  // Call the strongly typed version.
227  return Equals(obj as System.Collections.Generic.IEnumerable<T>);
228  }
229 
232  public override int GetHashCode()
233  {
234  // Call the static method, passing this.
235  return GetHashCode(this);
236  }
237 
238 #if __MonoCS__
239  public static int GetHashCode<T>(System.Collections.Generic.IEnumerable<T> source)
240 #else
245  public static int GetHashCode(System.Collections.Generic.IEnumerable<T> source)
246 #endif
247  {
248  // If source is null, then return 0.
249  if (source == null) return 0;
250 
251  // Seed the hash code with the hash code of the type.
252  // This is done so that you don't have a lot of collisions of empty
253  // ComparableList instances when placed in dictionaries
254  // and things that rely on hashcodes.
255  int hashCode = typeof(T).GetHashCode();
256 
257  // Iterate through the items in this implementation.
258  foreach (T item in source)
259  {
260  // Adjust the hash code.
261  hashCode = 31 * hashCode + (item == null ? 0 : item.GetHashCode());
262  }
263 
264  // Return the hash code.
265  return hashCode;
266  }
267 
268  // TODO: When diverging from Java version of Lucene, can uncomment these to adhere to best practices when overriding the Equals method and implementing IEquatable<T>.
277  //public static bool operator ==(EquatableList<T> x, System.Collections.Generic.IEnumerable<T> y)
278  //{
279  // // Call Equals.
280  // return Equals(x, y);
281  //}
282 
291  //public static bool operator ==(System.Collections.Generic.IEnumerable<T> x, EquatableList<T> y)
292  //{
293  // // Call equals.
294  // return Equals(x, y);
295  //}
296 
305  //public static bool operator !=(EquatableList<T> x, System.Collections.Generic.IEnumerable<T> y)
306  //{
307  // // Return the negative of the equals operation.
308  // return !(x == y);
309  //}
310 
319  //public static bool operator !=(System.Collections.Generic.IEnumerable<T> x, EquatableList<T> y)
320  //{
321  // // Return the negative of the equals operation.
322  // return !(x == y);
323  //}
324 
325  #region ICloneable Members
326 
331  public object Clone()
332  {
333  // Just create a new one, passing this to the constructor.
334  return new EquatableList<T>(this);
335  }
336 
337  #endregion
338  }
339 }