1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
15 using System; using Microsoft;
18 using System.Collections.Generic;
19 using System.Collections.ObjectModel;
20 using System.Diagnostics;
21 using System.Runtime.CompilerServices;
23 using Microsoft.Runtime.CompilerServices;
28 namespace System.Dynamic.Utils {
30 namespace Microsoft.Scripting.Utils {
32 internal static class CollectionExtensions {
34 /// Wraps the provided enumerable into a ReadOnlyCollection{T}
36 /// Copies all of the data into a new array, so the data can't be
37 /// changed after creation. The exception is if the enumerable is
38 /// already a ReadOnlyCollection{T}, in which case we just return it.
40 internal static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> enumerable) {
41 if (enumerable == null) {
42 return EmptyReadOnlyCollection<T>.Instance;
45 var troc = enumerable as TrueReadOnlyCollection<T>;
50 var builder = enumerable as ReadOnlyCollectionBuilder<T>;
51 if (builder != null) {
52 return builder.ToReadOnlyCollection();
55 var collection = enumerable as ICollection<T>;
56 if (collection != null) {
57 int count = collection.Count;
59 return EmptyReadOnlyCollection<T>.Instance;
62 T[] clone = new T[count];
63 collection.CopyTo(clone, 0);
64 return new TrueReadOnlyCollection<T>(clone);
67 // ToArray trims the excess space and speeds up access
68 return new TrueReadOnlyCollection<T>(new List<T>(enumerable).ToArray());
71 // We could probably improve the hashing here
72 internal static int ListHashCode<T>(this IEnumerable<T> list) {
73 var cmp = EqualityComparer<T>.Default;
75 foreach (T t in list) {
76 h ^= (h << 5) ^ cmp.GetHashCode(t);
81 internal static bool ListEquals<T>(this ICollection<T> first, ICollection<T> second) {
82 if (first.Count != second.Count) {
85 var cmp = EqualityComparer<T>.Default;
86 var f = first.GetEnumerator();
87 var s = second.GetEnumerator();
88 while (f.MoveNext()) {
91 if (!cmp.Equals(f.Current, s.Current)) {
98 internal static IEnumerable<U> Select<T, U>(this IEnumerable<T> enumerable, Func<T, U> select) {
99 foreach (T t in enumerable) {
100 yield return select(t);
104 // Name needs to be different so it doesn't conflict with Enumerable.Select
105 internal static U[] Map<T, U>(this ICollection<T> collection, Func<T, U> select) {
106 int count = collection.Count;
107 U[] result = new U[count];
109 foreach (T t in collection) {
110 result[count++] = select(t);
115 internal static IEnumerable<T> Where<T>(this IEnumerable<T> enumerable, Func<T, bool> where) {
116 foreach (T t in enumerable) {
123 internal static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
124 foreach (T element in source) {
125 if (predicate(element)) {
132 internal static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
133 foreach (T element in source) {
134 if (!predicate(element)) {
141 internal static T[] RemoveFirst<T>(this T[] array) {
142 T[] result = new T[array.Length - 1];
143 Array.Copy(array, 1, result, 0, result.Length);
147 internal static T[] RemoveLast<T>(this T[] array) {
148 T[] result = new T[array.Length - 1];
149 Array.Copy(array, 0, result, 0, result.Length);
153 internal static T[] AddFirst<T>(this IList<T> list, T item) {
154 T[] res = new T[list.Count + 1];
160 internal static T[] AddLast<T>(this IList<T> list, T item) {
161 T[] res = new T[list.Count + 1];
163 res[list.Count] = item;
167 internal static T First<T>(this IEnumerable<T> source) {
168 var list = source as IList<T>;
172 using (var e = source.GetEnumerator()) {
173 if (e.MoveNext()) return e.Current;
175 throw new InvalidOperationException();
178 internal static T Last<T>(this IList<T> list) {
179 return list[list.Count - 1];
182 internal static T[] Copy<T>(this T[] array) {
183 T[] copy = new T[array.Length];
184 Array.Copy(array, copy, array.Length);
190 internal static class EmptyReadOnlyCollection<T> {
191 internal static ReadOnlyCollection<T> Instance = new TrueReadOnlyCollection<T>(new T[0]);