mscorlib(4.0.0.0) API with additions
Lookup.cs
1 using System.Collections;
3 
4 namespace System.Linq
5 {
9  [global::__DynamicallyInvokable]
10  public class Lookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable, ILookup<TKey, TElement>
11  {
12  internal class Grouping : IGrouping<TKey, TElement>, IEnumerable<TElement>, IEnumerable, IList<TElement>, ICollection<TElement>
13  {
14  internal TKey key;
15 
16  internal int hashCode;
17 
18  internal TElement[] elements;
19 
20  internal int count;
21 
22  internal Grouping hashNext;
23 
24  internal Grouping next;
25 
26  public TKey Key => key;
27 
29  {
30  get
31  {
32  return count;
33  }
34  }
35 
36  bool ICollection<TElement>.IsReadOnly
37  {
38  get
39  {
40  return true;
41  }
42  }
43 
44  TElement IList<TElement>.this[int index]
45  {
46  get
47  {
48  if (index < 0 || index >= count)
49  {
50  throw Error.ArgumentOutOfRange("index");
51  }
52  return elements[index];
53  }
54  set
55  {
56  throw Error.NotSupported();
57  }
58  }
59 
60  internal void Add(TElement element)
61  {
62  if (elements.Length == count)
63  {
64  Array.Resize(ref elements, checked(count * 2));
65  }
66  elements[count] = element;
67  count++;
68  }
69 
71  {
72  for (int i = 0; i < count; i++)
73  {
74  yield return elements[i];
75  }
76  }
77 
79  {
80  return GetEnumerator();
81  }
82 
83  void ICollection<TElement>.Add(TElement item)
84  {
85  throw Error.NotSupported();
86  }
87 
88  void ICollection<TElement>.Clear()
89  {
90  throw Error.NotSupported();
91  }
92 
93  bool ICollection<TElement>.Contains(TElement item)
94  {
95  return Array.IndexOf(elements, item, 0, count) >= 0;
96  }
97 
98  void ICollection<TElement>.CopyTo(TElement[] array, int arrayIndex)
99  {
100  Array.Copy(elements, 0, array, arrayIndex, count);
101  }
102 
103  bool ICollection<TElement>.Remove(TElement item)
104  {
105  throw Error.NotSupported();
106  }
107 
108  int IList<TElement>.IndexOf(TElement item)
109  {
110  return Array.IndexOf(elements, item, 0, count);
111  }
112 
113  void IList<TElement>.Insert(int index, TElement item)
114  {
115  throw Error.NotSupported();
116  }
117 
118  void IList<TElement>.RemoveAt(int index)
119  {
120  throw Error.NotSupported();
121  }
122  }
123 
124  private IEqualityComparer<TKey> comparer;
125 
126  private Grouping[] groupings;
127 
128  private Grouping lastGrouping;
129 
130  private int count;
131 
134  [global::__DynamicallyInvokable]
135  public int Count
136  {
137  [global::__DynamicallyInvokable]
138  get
139  {
140  return count;
141  }
142  }
143 
147  [global::__DynamicallyInvokable]
148  public IEnumerable<TElement> this[TKey key]
149  {
150  [global::__DynamicallyInvokable]
151  get
152  {
153  Grouping grouping = GetGrouping(key, create: false);
154  if (grouping != null)
155  {
156  return grouping;
157  }
158  return EmptyEnumerable<TElement>.Instance;
159  }
160  }
161 
162  internal static Lookup<TKey, TElement> Create<TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
163  {
164  if (source == null)
165  {
166  throw Error.ArgumentNull("source");
167  }
168  if (keySelector == null)
169  {
170  throw Error.ArgumentNull("keySelector");
171  }
172  if (elementSelector == null)
173  {
174  throw Error.ArgumentNull("elementSelector");
175  }
176  Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
177  foreach (TSource item in source)
178  {
179  lookup.GetGrouping(keySelector(item), create: true).Add(elementSelector(item));
180  }
181  return lookup;
182  }
183 
184  internal static Lookup<TKey, TElement> CreateForJoin(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
185  {
186  Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
187  foreach (TElement item in source)
188  {
189  TKey val = keySelector(item);
190  if (val != null)
191  {
192  lookup.GetGrouping(val, create: true).Add(item);
193  }
194  }
195  return lookup;
196  }
197 
198  private Lookup(IEqualityComparer<TKey> comparer)
199  {
200  if (comparer == null)
201  {
202  comparer = EqualityComparer<TKey>.Default;
203  }
204  this.comparer = comparer;
205  groupings = new Grouping[7];
206  }
207 
212  [global::__DynamicallyInvokable]
213  public bool Contains(TKey key)
214  {
215  return GetGrouping(key, create: false) != null;
216  }
217 
220  [global::__DynamicallyInvokable]
222  {
223  Grouping g = lastGrouping;
224  if (g != null)
225  {
226  do
227  {
228  g = g.next;
229  yield return g;
230  }
231  while (g != lastGrouping);
232  }
233  }
234 
239  [global::__DynamicallyInvokable]
240  public IEnumerable<TResult> ApplyResultSelector<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
241  {
242  Grouping g = lastGrouping;
243  if (g == null)
244  {
245  yield break;
246  }
247  do
248  {
249  g = g.next;
250  if (g.count != g.elements.Length)
251  {
252  Array.Resize(ref g.elements, g.count);
253  }
254  yield return resultSelector(g.key, g.elements);
255  }
256  while (g != lastGrouping);
257  }
258 
261  [global::__DynamicallyInvokable]
263  {
264  return GetEnumerator();
265  }
266 
267  internal int InternalGetHashCode(TKey key)
268  {
269  if (key != null)
270  {
271  return comparer.GetHashCode(key) & int.MaxValue;
272  }
273  return 0;
274  }
275 
276  internal Grouping GetGrouping(TKey key, bool create)
277  {
278  int num = InternalGetHashCode(key);
279  for (Grouping grouping = groupings[num % groupings.Length]; grouping != null; grouping = grouping.hashNext)
280  {
281  if (grouping.hashCode == num && comparer.Equals(grouping.key, key))
282  {
283  return grouping;
284  }
285  }
286  if (create)
287  {
288  if (count == groupings.Length)
289  {
290  Resize();
291  }
292  int num2 = num % groupings.Length;
293  Grouping grouping2 = new Grouping();
294  grouping2.key = key;
295  grouping2.hashCode = num;
296  grouping2.elements = new TElement[1];
297  grouping2.hashNext = groupings[num2];
298  groupings[num2] = grouping2;
299  if (lastGrouping == null)
300  {
301  grouping2.next = grouping2;
302  }
303  else
304  {
305  grouping2.next = lastGrouping.next;
306  lastGrouping.next = grouping2;
307  }
308  lastGrouping = grouping2;
309  count++;
310  return grouping2;
311  }
312  return null;
313  }
314 
315  private void Resize()
316  {
317  int num = checked(count * 2 + 1);
318  Grouping[] array = new Grouping[num];
319  Grouping next = lastGrouping;
320  do
321  {
322  next = next.next;
323  int num2 = next.hashCode % num;
324  next.hashNext = array[num2];
325  array[num2] = next;
326  }
327  while (next != lastGrouping);
328  groupings = array;
329  }
330  }
331 }
Provides a base class for implementations of the T:System.Collections.Generic.IEqualityComparer`1 gen...
Represents a non-generic collection of objects that can be individually accessed by index.
Definition: IList.cs:8
void RemoveAt(int index)
Removes the T:System.Collections.IList item at the specified index.
void Insert(int index, object value)
Inserts an item to the T:System.Collections.IList at the specified index.
Definition: __Canon.cs:3
IEnumerable< TResult > ApplyResultSelector< TResult >(Func< TKey, IEnumerable< TElement >, TResult > resultSelector)
Applies a transform function to each key and its associated values and returns the results.
Definition: Lookup.cs:240
IEnumerator< IGrouping< TKey, TElement > > GetEnumerator()
Returns a generic enumerator that iterates through the T:System.Linq.Lookup`2.
Definition: Lookup.cs:221
int IndexOf(object value)
Determines the index of a specific item in the T:System.Collections.IList.
Represents a collection of objects that have a common key.
Definition: IGrouping.cs:10
static EqualityComparer< T > Default
Returns a default equality comparer for the type specified by the generic argument.
Exposes an enumerator, which supports a simple iteration over a non-generic collection....
Definition: IEnumerable.cs:9
new bool Equals(object x, object y)
Determines whether the specified objects are equal.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition: Array.cs:17
Defines an indexer, size property, and Boolean search method for data structures that map keys to T:S...
Definition: ILookup.cs:10
Represents a collection of keys each mapped to one or more values.
Definition: Lookup.cs:10
IEnumerator GetEnumerator()
Returns an enumerator that iterates through a collection.
int GetHashCode(object obj)
Returns a hash code for the specified object.
static void Copy(Array sourceArray, Array destinationArray, int length)
Copies a range of elements from an T:System.Array starting at the first element and pastes them into ...
Definition: Array.cs:1275
int Count
Gets the number of key/value collection pairs in the T:System.Linq.Lookup`2.
Definition: Lookup.cs:136
int Count
Gets the number of elements contained in the T:System.Collections.ICollection.
Definition: ICollection.cs:14
Defines size, enumerators, and synchronization methods for all nongeneric collections.
Definition: ICollection.cs:8
void CopyTo(Array array, int index)
Copies the elements of the T:System.Collections.ICollection to an T:System.Array, starting at a parti...
bool Contains(TKey key)
Determines whether a specified key is in the T:System.Linq.Lookup`2.
Definition: Lookup.cs:213