1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Collections;
18 using System.Collections.Generic;
20 namespace Microsoft.Scripting.Utils {
22 /// Allows wrapping of proxy types (like COM RCWs) to expose their IEnumerable functionality
23 /// which is supported after casting to IEnumerable, even though Reflection will not indicate
24 /// IEnumerable as a supported interface
26 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1010:CollectionsShouldImplementGenericInterface")] // TODO
27 public class EnumerableWrapper : IEnumerable {
28 private IEnumerable _wrappedObject;
29 public EnumerableWrapper(IEnumerable o) {
33 public IEnumerator GetEnumerator() {
34 return _wrappedObject.GetEnumerator();
38 public static class CollectionUtils {
40 public static IEnumerable<T> Cast<S, T>(this IEnumerable<S> sequence) where S : T {
41 foreach (var item in sequence) {
46 public static IEnumerable<T> Cast<S, T>(this IEnumerable<S> sequence) where S : T {
47 return (IEnumerable<T>)sequence;
51 public static IEnumerable<TSuper> ToCovariant<T, TSuper>(IEnumerable<T> enumerable)
54 return (IEnumerable<TSuper>)enumerable;
56 return new CovariantConvertor<T, TSuper>(enumerable);
60 public static void AddRange<T>(ICollection<T> collection, IEnumerable<T> items) {
61 ContractUtils.RequiresNotNull(collection, "collection");
62 ContractUtils.RequiresNotNull(items, "items");
64 List<T> list = collection as List<T>;
68 foreach (T item in items) {
74 public static void AddRange<T>(this IList<T> list, IEnumerable<T> items) {
75 foreach (var item in items) {
80 public static IEnumerable<T> ToEnumerable<T>(IEnumerable enumerable) {
81 foreach (T item in enumerable) {
86 public static IEnumerator<TSuper> ToCovariant<T, TSuper>(IEnumerator<T> enumerator)
89 ContractUtils.RequiresNotNull(enumerator, "enumerator");
91 while (enumerator.MoveNext()) {
92 yield return enumerator.Current;
96 private class CovariantConvertor<T, TSuper> : IEnumerable<TSuper> where T : TSuper {
97 private IEnumerable<T> _enumerable;
99 public CovariantConvertor(IEnumerable<T> enumerable) {
100 ContractUtils.RequiresNotNull(enumerable, "enumerable");
101 _enumerable = enumerable;
104 public IEnumerator<TSuper> GetEnumerator() {
105 return CollectionUtils.ToCovariant<T, TSuper>(_enumerable.GetEnumerator());
108 IEnumerator IEnumerable.GetEnumerator() {
109 return GetEnumerator();
113 public static IDictionaryEnumerator ToDictionaryEnumerator(IEnumerator<KeyValuePair<object, object>> enumerator) {
114 return new DictionaryEnumerator(enumerator);
117 private sealed class DictionaryEnumerator : IDictionaryEnumerator {
118 private readonly IEnumerator<KeyValuePair<object, object>> _enumerator;
120 public DictionaryEnumerator(IEnumerator<KeyValuePair<object, object>> enumerator) {
121 _enumerator = enumerator;
124 public DictionaryEntry Entry {
125 get { return new DictionaryEntry(_enumerator.Current.Key, _enumerator.Current.Value); }
129 get { return _enumerator.Current.Key; }
132 public object Value {
133 get { return _enumerator.Current.Value; }
136 public object Current {
137 get { return Entry; }
140 public bool MoveNext() {
141 return _enumerator.MoveNext();
144 public void Reset() {
149 public static List<T> MakeList<T>(T item) {
150 List<T> result = new List<T>();
155 public static int CountOf<T>(IList<T> list, T item) where T : IEquatable<T> {
156 if (list == null) return 0;
159 for (int i = 0; i < list.Count; i++) {
160 if (list[i].Equals(item)) {
167 public static int Max(this IEnumerable<int> values) {
168 ContractUtils.RequiresNotNull(values, "values");
170 int result = Int32.MinValue;
171 foreach (var value in values) {
172 if (value > result) {
179 public static bool TrueForAll<T>(IEnumerable<T> collection, Predicate<T> predicate) {
180 ContractUtils.RequiresNotNull(collection, "collection");
181 ContractUtils.RequiresNotNull(predicate, "predicate");
183 foreach (T item in collection) {
184 if (!predicate(item)) return false;
190 public static IList<TRet> ConvertAll<T, TRet>(IList<T> collection, Func<T, TRet> predicate) {
191 ContractUtils.RequiresNotNull(collection, "collection");
192 ContractUtils.RequiresNotNull(predicate, "predicate");
194 List<TRet> res = new List<TRet>(collection.Count);
195 foreach (T item in collection) {
196 res.Add(predicate(item));
202 public static List<T> GetRange<T>(IList<T> list, int index, int count) {
203 ContractUtils.RequiresNotNull(list, "list");
204 ContractUtils.RequiresArrayRange(list, index, count, "index", "count");
206 List<T> result = new List<T>(count);
207 int stop = index + count;
208 for (int i = index; i < stop; i++) {
214 public static void InsertRange<T>(IList<T> collection, int index, IEnumerable<T> items) {
215 ContractUtils.RequiresNotNull(collection, "collection");
216 ContractUtils.RequiresNotNull(items, "items");
217 ContractUtils.RequiresArrayInsertIndex(collection, index, "index");
219 List<T> list = collection as List<T>;
221 list.InsertRange(index, items);
224 foreach (T obj in items) {
225 collection.Insert(i++, obj);
230 public static void RemoveRange<T>(IList<T> collection, int index, int count) {
231 ContractUtils.RequiresNotNull(collection, "collection");
232 ContractUtils.RequiresArrayRange(collection, index, count, "index", "count");
234 List<T> list = collection as List<T>;
236 list.RemoveRange(index, count);
238 for (int i = index + count - 1; i >= index; i--) {
239 collection.RemoveAt(i);
244 public static int FindIndex<T>(this IList<T> collection, Predicate<T> predicate) {
245 ContractUtils.RequiresNotNull(collection, "collection");
246 ContractUtils.RequiresNotNull(predicate, "predicate");
248 for (int i = 0; i < collection.Count; i++) {
249 if (predicate(collection[i])) {
256 public static IList<T> ToSortedList<T>(this ICollection<T> collection, Comparison<T> comparison) {
257 ContractUtils.RequiresNotNull(collection, "collection");
258 ContractUtils.RequiresNotNull(comparison, "comparison");
260 var array = new T[collection.Count];
261 collection.CopyTo(array, 0);
262 Array.Sort(array, comparison);
266 public static T[] ToReverseArray<T>(this IList<T> list) {
267 ContractUtils.RequiresNotNull(list, "list");
268 T[] result = new T[list.Count];
269 for (int i = 0; i < result.Length; i++) {
270 result[i] = list[result.Length - 1 - i];
276 #if SILVERLIGHT || WIN8 || WP75
277 // HashSet.CreateSetComparer not available on Silverlight
278 public static IEqualityComparer<HashSet<T>> CreateSetComparer<T>() {
279 return new HashSetEqualityComparer<T>();
282 class HashSetEqualityComparer<T> : IEqualityComparer<HashSet<T>> {
283 private IEqualityComparer<T> _comparer;
285 public HashSetEqualityComparer() {
286 _comparer = EqualityComparer<T>.Default;
289 public bool Equals(HashSet<T> x, HashSet<T> y) {
292 } else if (x == null || y == null || x.Count != y.Count) {
296 foreach (T value in x) {
297 if (!y.Contains(value)) {
305 public int GetHashCode(HashSet<T> obj) {
308 foreach (T t in obj) {
309 res = res ^ _comparer.GetHashCode(t);
317 public static IEqualityComparer<HashSet<T>> CreateSetComparer<T>() {
318 return HashSet<T>.CreateSetComparer();