PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/JsonDotNetUnity/Scripts/JsonNetUnity/Utilities/CollectionUtils.cs

https://gitlab.com/sheetanshusrivastava3/Unity3D-code-repository-design-patterns
C# | 763 lines | 538 code | 121 blank | 104 comment | 125 complexity | 859ae38bec3737be1ce15845e6bcb5c5 MD5 | raw file
  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System;
  26. using System.Collections.Generic;
  27. using System.Collections.ObjectModel;
  28. using System.Reflection;
  29. using System.Text;
  30. using System.Collections;
  31. using System.Linq;
  32. using System.Globalization;
  33. namespace Newtonsoft.Json.Utilities
  34. {
  35. internal static class CollectionUtils
  36. {
  37. public static IEnumerable<T> CastValid<T>(this IEnumerable enumerable)
  38. {
  39. ValidationUtils.ArgumentNotNull(enumerable, "enumerable");
  40. return enumerable.Cast<object>().Where(o => o is T).Cast<T>();
  41. }
  42. public static List<T> CreateList<T>(params T[] values)
  43. {
  44. return new List<T>(values);
  45. }
  46. /// <summary>
  47. /// Determines whether the collection is null or empty.
  48. /// </summary>
  49. /// <param name="collection">The collection.</param>
  50. /// <returns>
  51. /// <c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
  52. /// </returns>
  53. public static bool IsNullOrEmpty(ICollection collection)
  54. {
  55. if (collection != null)
  56. {
  57. return (collection.Count == 0);
  58. }
  59. return true;
  60. }
  61. /// <summary>
  62. /// Determines whether the collection is null or empty.
  63. /// </summary>
  64. /// <param name="collection">The collection.</param>
  65. /// <returns>
  66. /// <c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
  67. /// </returns>
  68. public static bool IsNullOrEmpty<T>(ICollection<T> collection)
  69. {
  70. if (collection != null)
  71. {
  72. return (collection.Count == 0);
  73. }
  74. return true;
  75. }
  76. /// <summary>
  77. /// Determines whether the collection is null, empty or its contents are uninitialized values.
  78. /// </summary>
  79. /// <param name="list">The list.</param>
  80. /// <returns>
  81. /// <c>true</c> if the collection is null or empty or its contents are uninitialized values; otherwise, <c>false</c>.
  82. /// </returns>
  83. public static bool IsNullOrEmptyOrDefault<T>(IList<T> list)
  84. {
  85. if (IsNullOrEmpty<T>(list))
  86. return true;
  87. return ReflectionUtils.ItemsUnitializedValue<T>(list);
  88. }
  89. /// <summary>
  90. /// Makes a slice of the specified list in between the start and end indexes.
  91. /// </summary>
  92. /// <param name="list">The list.</param>
  93. /// <param name="start">The start index.</param>
  94. /// <param name="end">The end index.</param>
  95. /// <returns>A slice of the list.</returns>
  96. public static IList<T> Slice<T>(IList<T> list, int? start, int? end)
  97. {
  98. return Slice<T>(list, start, end, null);
  99. }
  100. /// <summary>
  101. /// Makes a slice of the specified list in between the start and end indexes,
  102. /// getting every so many items based upon the step.
  103. /// </summary>
  104. /// <param name="list">The list.</param>
  105. /// <param name="start">The start index.</param>
  106. /// <param name="end">The end index.</param>
  107. /// <param name="step">The step.</param>
  108. /// <returns>A slice of the list.</returns>
  109. public static IList<T> Slice<T>(IList<T> list, int? start, int? end, int? step)
  110. {
  111. if (list == null)
  112. throw new ArgumentNullException("list");
  113. if (step == 0)
  114. throw new ArgumentException("Step cannot be zero.", "step");
  115. List<T> slicedList = new List<T>();
  116. // nothing to slice
  117. if (list.Count == 0)
  118. return slicedList;
  119. // set defaults for null arguments
  120. int s = step ?? 1;
  121. int startIndex = start ?? 0;
  122. int endIndex = end ?? list.Count;
  123. // start from the end of the list if start is negitive
  124. startIndex = (startIndex < 0) ? list.Count + startIndex : startIndex;
  125. // end from the start of the list if end is negitive
  126. endIndex = (endIndex < 0) ? list.Count + endIndex : endIndex;
  127. // ensure indexes keep within collection bounds
  128. startIndex = Math.Max(startIndex, 0);
  129. endIndex = Math.Min(endIndex, list.Count - 1);
  130. // loop between start and end indexes, incrementing by the step
  131. for (int i = startIndex; i < endIndex; i += s)
  132. {
  133. slicedList.Add(list[i]);
  134. }
  135. return slicedList;
  136. }
  137. /// <summary>
  138. /// Group the collection using a function which returns the key.
  139. /// </summary>
  140. /// <param name="source">The source collection to group.</param>
  141. /// <param name="keySelector">The key selector.</param>
  142. /// <returns>A Dictionary with each key relating to a list of objects in a list grouped under it.</returns>
  143. public static Dictionary<K, List<V>> GroupBy<K, V>(ICollection<V> source, Func<V, K> keySelector)
  144. {
  145. if (keySelector == null)
  146. throw new ArgumentNullException("keySelector");
  147. Dictionary<K, List<V>> groupedValues = new Dictionary<K, List<V>>();
  148. #if (UNITY_IPHONE || UNITY_IOS)
  149. var sourceArray = source.ToArray();
  150. for (var i = 0; i < sourceArray.Length; i++)
  151. {
  152. var value = sourceArray[i];
  153. // using delegate to get the value's key
  154. K key = keySelector(value);
  155. List<V> groupedValueList;
  156. // add a list for grouped values if the key is not already in Dictionary
  157. if (!groupedValues.TryGetValue(key, out groupedValueList))
  158. {
  159. groupedValueList = new List<V>();
  160. groupedValues.Add(key, groupedValueList);
  161. }
  162. groupedValueList.Add(value);
  163. }
  164. #else
  165. foreach (V value in source)
  166. {
  167. // using delegate to get the value's key
  168. K key = keySelector(value);
  169. List<V> groupedValueList;
  170. // add a list for grouped values if the key is not already in Dictionary
  171. if (!groupedValues.TryGetValue(key, out groupedValueList))
  172. {
  173. groupedValueList = new List<V>();
  174. groupedValues.Add(key, groupedValueList);
  175. }
  176. groupedValueList.Add(value);
  177. }
  178. #endif
  179. return groupedValues;
  180. }
  181. /// <summary>
  182. /// Adds the elements of the specified collection to the specified generic IList.
  183. /// </summary>
  184. /// <param name="initial">The list to add to.</param>
  185. /// <param name="collection">The collection of elements to add.</param>
  186. public static void AddRange<T>(this IList<T> initial, IEnumerable<T> collection)
  187. {
  188. if (initial == null)
  189. throw new ArgumentNullException("initial");
  190. if (collection == null)
  191. return;
  192. #if (UNITY_IPHONE || UNITY_IOS)
  193. var collArray = collection.ToArray();
  194. for (var i = 0; i < collArray.Length; i++)
  195. {
  196. initial.Add(collArray[i]);
  197. }
  198. #else
  199. foreach (T value in collection)
  200. {
  201. initial.Add(value);
  202. }
  203. #endif
  204. }
  205. public static void AddRange(this IList initial, IEnumerable collection)
  206. {
  207. ValidationUtils.ArgumentNotNull(initial, "initial");
  208. ListWrapper<object> wrapper = new ListWrapper<object>(initial);
  209. wrapper.AddRange(collection.Cast<object>());
  210. }
  211. public static List<T> Distinct<T>(List<T> collection)
  212. {
  213. List<T> distinctList = new List<T>();
  214. #if (UNITY_IPHONE || UNITY_IOS)
  215. var colArray = collection.ToArray();
  216. for(var i = 0; i < colArray.Length; i++)
  217. {
  218. if (!distinctList.Contains(colArray[i]))
  219. distinctList.Add(colArray[i]);
  220. }
  221. #else
  222. foreach (T value in collection)
  223. {
  224. if (!distinctList.Contains(value))
  225. distinctList.Add(value);
  226. }
  227. #endif
  228. return distinctList;
  229. }
  230. public static List<List<T>> Flatten<T>(params IList<T>[] lists)
  231. {
  232. List<List<T>> flattened = new List<List<T>>();
  233. Dictionary<int, T> currentList = new Dictionary<int, T>();
  234. Recurse<T>(new List<IList<T>>(lists), 0, currentList, flattened);
  235. return flattened;
  236. }
  237. private static void Recurse<T>(IList<IList<T>> global, int current, Dictionary<int, T> currentSet, List<List<T>> flattenedResult)
  238. {
  239. IList<T> currentArray = global[current];
  240. for (int i = 0; i < currentArray.Count; i++)
  241. {
  242. currentSet[current] = currentArray[i];
  243. if (current == global.Count - 1)
  244. {
  245. List<T> items = new List<T>();
  246. for (int k = 0; k < currentSet.Count; k++)
  247. {
  248. items.Add(currentSet[k]);
  249. }
  250. flattenedResult.Add(items);
  251. }
  252. else
  253. {
  254. Recurse(global, current + 1, currentSet, flattenedResult);
  255. }
  256. }
  257. }
  258. public static List<T> CreateList<T>(ICollection collection)
  259. {
  260. if (collection == null)
  261. throw new ArgumentNullException("collection");
  262. T[] array = new T[collection.Count];
  263. collection.CopyTo(array, 0);
  264. return new List<T>(array);
  265. }
  266. public static bool ListEquals<T>(IList<T> a, IList<T> b)
  267. {
  268. if (a == null || b == null)
  269. return (a == null && b == null);
  270. if (a.Count != b.Count)
  271. return false;
  272. EqualityComparer<T> comparer = EqualityComparer<T>.Default;
  273. for (int i = 0; i < a.Count; i++)
  274. {
  275. if (!comparer.Equals(a[i], b[i]))
  276. return false;
  277. }
  278. return true;
  279. }
  280. #region GetSingleItem
  281. public static bool TryGetSingleItem<T>(IList<T> list, out T value)
  282. {
  283. return TryGetSingleItem<T>(list, false, out value);
  284. }
  285. public static bool TryGetSingleItem<T>(IList<T> list, bool returnDefaultIfEmpty, out T value)
  286. {
  287. return MiscellaneousUtils.TryAction<T>(delegate { return GetSingleItem(list, returnDefaultIfEmpty); }, out value);
  288. }
  289. public static T GetSingleItem<T>(IList<T> list)
  290. {
  291. return GetSingleItem<T>(list, false);
  292. }
  293. public static T GetSingleItem<T>(IList<T> list, bool returnDefaultIfEmpty)
  294. {
  295. if (list.Count == 1)
  296. return list[0];
  297. else if (returnDefaultIfEmpty && list.Count == 0)
  298. return default(T);
  299. else
  300. throw new Exception("Expected single {0} in list but got {1}.".FormatWith(CultureInfo.InvariantCulture, typeof(T), list.Count));
  301. }
  302. #endregion
  303. public static IList<T> Minus<T>(IList<T> list, IList<T> minus)
  304. {
  305. ValidationUtils.ArgumentNotNull(list, "list");
  306. List<T> result = new List<T>(list.Count);
  307. #if (UNITY_IPHONE || UNITY_IOS)
  308. var itemArray = list.ToArray();
  309. for(var i = 0; i < itemArray.Length; i++)
  310. {
  311. if (minus == null || !minus.Contains(itemArray[i]))
  312. result.Add(itemArray[i]);
  313. }
  314. #else
  315. foreach (T t in list)
  316. {
  317. if (minus == null || !minus.Contains(t))
  318. result.Add(t);
  319. }
  320. #endif
  321. return result;
  322. }
  323. public static IList CreateGenericList(Type listType)
  324. {
  325. ValidationUtils.ArgumentNotNull(listType, "listType");
  326. return (IList)ReflectionUtils.CreateGeneric(typeof(List<>), listType);
  327. }
  328. public static IDictionary CreateGenericDictionary(Type keyType, Type valueType)
  329. {
  330. ValidationUtils.ArgumentNotNull(keyType, "keyType");
  331. ValidationUtils.ArgumentNotNull(valueType, "valueType");
  332. return (IDictionary)ReflectionUtils.CreateGeneric(typeof(Dictionary<,>), keyType, valueType);
  333. }
  334. public static bool IsListType(Type type)
  335. {
  336. ValidationUtils.ArgumentNotNull(type, "type");
  337. if (type.IsArray)
  338. return true;
  339. if (typeof(IList).IsAssignableFrom(type))
  340. return true;
  341. if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IList<>)))
  342. return true;
  343. return false;
  344. }
  345. public static bool IsCollectionType(Type type)
  346. {
  347. ValidationUtils.ArgumentNotNull(type, "type");
  348. if (type.IsArray)
  349. return true;
  350. if (typeof(ICollection).IsAssignableFrom(type))
  351. return true;
  352. if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(ICollection<>)))
  353. return true;
  354. return false;
  355. }
  356. public static bool IsDictionaryType(Type type)
  357. {
  358. ValidationUtils.ArgumentNotNull(type, "type");
  359. if (typeof(IDictionary).IsAssignableFrom(type))
  360. return true;
  361. if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IDictionary<,>)))
  362. return true;
  363. return false;
  364. }
  365. public static IWrappedCollection CreateCollectionWrapper(object list)
  366. {
  367. ValidationUtils.ArgumentNotNull(list, "list");
  368. Type collectionDefinition;
  369. if (ReflectionUtils.ImplementsGenericDefinition(list.GetType(), typeof(ICollection<>), out collectionDefinition))
  370. {
  371. Type collectionItemType = ReflectionUtils.GetCollectionItemType(collectionDefinition);
  372. // Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor
  373. Func<Type, IList<object>, object> instanceCreator = (t, a) =>
  374. {
  375. ConstructorInfo c = t.GetConstructor(new[] { collectionDefinition });
  376. return c.Invoke(new[] { list });
  377. };
  378. return (IWrappedCollection)ReflectionUtils.CreateGeneric(typeof(CollectionWrapper<>), new[] { collectionItemType }, instanceCreator, list);
  379. }
  380. else if (list is IList)
  381. {
  382. return new CollectionWrapper<object>((IList)list);
  383. }
  384. else
  385. {
  386. throw new Exception("Can not create ListWrapper for type {0}.".FormatWith(CultureInfo.InvariantCulture, list.GetType()));
  387. }
  388. }
  389. public static IWrappedList CreateListWrapper(object list)
  390. {
  391. ValidationUtils.ArgumentNotNull(list, "list");
  392. Type listDefinition;
  393. if (ReflectionUtils.ImplementsGenericDefinition(list.GetType(), typeof(IList<>), out listDefinition))
  394. {
  395. Type collectionItemType = ReflectionUtils.GetCollectionItemType(listDefinition);
  396. // Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor
  397. Func<Type, IList<object>, object> instanceCreator = (t, a) =>
  398. {
  399. ConstructorInfo c = t.GetConstructor(new[] { listDefinition });
  400. return c.Invoke(new[] { list });
  401. };
  402. return (IWrappedList)ReflectionUtils.CreateGeneric(typeof(ListWrapper<>), new[] { collectionItemType }, instanceCreator, list);
  403. }
  404. else if (list is IList)
  405. {
  406. return new ListWrapper<object>((IList)list);
  407. }
  408. else
  409. {
  410. throw new Exception("Can not create ListWrapper for type {0}.".FormatWith(CultureInfo.InvariantCulture, list.GetType()));
  411. }
  412. }
  413. public static IWrappedDictionary CreateDictionaryWrapper(object dictionary)
  414. {
  415. ValidationUtils.ArgumentNotNull(dictionary, "dictionary");
  416. Type dictionaryDefinition;
  417. if (ReflectionUtils.ImplementsGenericDefinition(dictionary.GetType(), typeof(IDictionary<,>), out dictionaryDefinition))
  418. {
  419. Type dictionaryKeyType = ReflectionUtils.GetDictionaryKeyType(dictionaryDefinition);
  420. Type dictionaryValueType = ReflectionUtils.GetDictionaryValueType(dictionaryDefinition);
  421. // Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor
  422. Func<Type, IList<object>, object> instanceCreator = (t, a) =>
  423. {
  424. ConstructorInfo c = t.GetConstructor(new[] { dictionaryDefinition });
  425. return c.Invoke(new[] { dictionary });
  426. };
  427. return (IWrappedDictionary)ReflectionUtils.CreateGeneric(typeof(DictionaryWrapper<,>), new[] { dictionaryKeyType, dictionaryValueType }, instanceCreator, dictionary);
  428. }
  429. else if (dictionary is IDictionary)
  430. {
  431. return new DictionaryWrapper<object, object>((IDictionary)dictionary);
  432. }
  433. else
  434. {
  435. throw new Exception("Can not create DictionaryWrapper for type {0}.".FormatWith(CultureInfo.InvariantCulture, dictionary.GetType()));
  436. }
  437. }
  438. public static object CreateAndPopulateList(Type listType, Action<IList, bool> populateList)
  439. {
  440. ValidationUtils.ArgumentNotNull(listType, "listType");
  441. ValidationUtils.ArgumentNotNull(populateList, "populateList");
  442. IList list;
  443. Type collectionType;
  444. bool isReadOnlyOrFixedSize = false;
  445. if (listType.IsArray)
  446. {
  447. // have to use an arraylist when creating array
  448. // there is no way to know the size until it is finised
  449. list = new List<object>();
  450. isReadOnlyOrFixedSize = true;
  451. }
  452. else if (ReflectionUtils.InheritsGenericDefinition(listType, typeof(ReadOnlyCollection<>), out collectionType))
  453. {
  454. Type readOnlyCollectionContentsType = collectionType.GetGenericArguments()[0];
  455. Type genericEnumerable = ReflectionUtils.MakeGenericType(typeof(IEnumerable<>), readOnlyCollectionContentsType);
  456. bool suitableConstructor = false;
  457. foreach (ConstructorInfo constructor in listType.GetConstructors())
  458. {
  459. IList<ParameterInfo> parameters = constructor.GetParameters();
  460. if (parameters.Count == 1)
  461. {
  462. if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
  463. {
  464. suitableConstructor = true;
  465. break;
  466. }
  467. }
  468. }
  469. if (!suitableConstructor)
  470. throw new Exception("Read-only type {0} does not have a public constructor that takes a type that implements {1}.".FormatWith(CultureInfo.InvariantCulture, listType, genericEnumerable));
  471. // can't add or modify a readonly list
  472. // use List<T> and convert once populated
  473. list = CreateGenericList(readOnlyCollectionContentsType);
  474. isReadOnlyOrFixedSize = true;
  475. }
  476. else if (typeof(IList).IsAssignableFrom(listType))
  477. {
  478. if (ReflectionUtils.IsInstantiatableType(listType))
  479. list = (IList)Activator.CreateInstance(listType);
  480. else if (listType == typeof(IList))
  481. list = new List<object>();
  482. else
  483. list = null;
  484. }
  485. else if (ReflectionUtils.ImplementsGenericDefinition(listType, typeof(ICollection<>)))
  486. {
  487. if (ReflectionUtils.IsInstantiatableType(listType))
  488. list = CreateCollectionWrapper(Activator.CreateInstance(listType));
  489. else
  490. list = null;
  491. }
  492. else
  493. {
  494. list = null;
  495. }
  496. if (list == null)
  497. throw new Exception("Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, listType));
  498. populateList(list, isReadOnlyOrFixedSize);
  499. // create readonly and fixed sized collections using the temporary list
  500. if (isReadOnlyOrFixedSize)
  501. {
  502. if (listType.IsArray)
  503. list = ToArray(((List<object>)list).ToArray(), ReflectionUtils.GetCollectionItemType(listType));
  504. else if (ReflectionUtils.InheritsGenericDefinition(listType, typeof(ReadOnlyCollection<>)))
  505. list = (IList)ReflectionUtils.CreateInstance(listType, list);
  506. }
  507. else if (list is IWrappedCollection)
  508. {
  509. return ((IWrappedCollection)list).UnderlyingCollection;
  510. }
  511. return list;
  512. }
  513. public static Array ToArray(Array initial, Type type)
  514. {
  515. if (type == null)
  516. throw new ArgumentNullException("type");
  517. Array destinationArray = Array.CreateInstance(type, initial.Length);
  518. Array.Copy(initial, 0, destinationArray, 0, initial.Length);
  519. return destinationArray;
  520. }
  521. public static bool AddDistinct<T>(this IList<T> list, T value)
  522. {
  523. return list.AddDistinct(value, EqualityComparer<T>.Default);
  524. }
  525. public static bool AddDistinct<T>(this IList<T> list, T value, IEqualityComparer<T> comparer)
  526. {
  527. if (list.ContainsValue(value, comparer))
  528. return false;
  529. list.Add(value);
  530. return true;
  531. }
  532. // this is here because LINQ Bridge doesn't support Contains with IEqualityComparer<T>
  533. public static bool ContainsValue<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
  534. {
  535. if (comparer == null)
  536. comparer = EqualityComparer<TSource>.Default;
  537. if (source == null)
  538. throw new ArgumentNullException("source");
  539. #if (UNITY_IPHONE || UNITY_IOS)
  540. var sourceArray = source.ToArray();
  541. for (var i = 0; i < sourceArray.Length; i++)
  542. {
  543. if (comparer.Equals(sourceArray[i], value))
  544. return true;
  545. }
  546. #else
  547. foreach (TSource local in source)
  548. {
  549. if (comparer.Equals(local, value))
  550. return true;
  551. }
  552. #endif
  553. return false;
  554. }
  555. public static bool AddRangeDistinct<T>(this IList<T> list, IEnumerable<T> values)
  556. {
  557. return list.AddRangeDistinct(values, EqualityComparer<T>.Default);
  558. }
  559. public static bool AddRangeDistinct<T>(this IList<T> list, IEnumerable<T> values, IEqualityComparer<T> comparer)
  560. {
  561. bool allAdded = true;
  562. #if (UNITY_IPHONE || UNITY_IOS)
  563. var valueArray = values.ToArray();
  564. for (var i = 0; i < valueArray.Length; i++)
  565. {
  566. if (!list.AddDistinct(valueArray[i], comparer))
  567. allAdded = false;
  568. }
  569. #else
  570. foreach (T value in values)
  571. {
  572. if (!list.AddDistinct(value, comparer))
  573. allAdded = false;
  574. }
  575. #endif
  576. return allAdded;
  577. }
  578. public static int IndexOf<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
  579. {
  580. #if (UNITY_IPHONE || UNITY_IOS)
  581. var collArray = collection.ToArray();
  582. for (var i = 0; i < collArray.Length; i++)
  583. {
  584. if (predicate(collArray[i]))
  585. return i;
  586. }
  587. #else
  588. int index = 0;
  589. foreach (T value in collection)
  590. {
  591. if (predicate(value))
  592. return index;
  593. index++;
  594. }
  595. #endif
  596. return -1;
  597. }
  598. /// <summary>
  599. /// Returns the index of the first occurrence in a sequence by using the default equality comparer.
  600. /// </summary>
  601. /// <typeparam name="TSource">The type of the elements of source.</typeparam>
  602. /// <param name="list">A sequence in which to locate a value.</param>
  603. /// <param name="value">The object to locate in the sequence</param>
  604. /// <returns>The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, –1.</returns>
  605. public static int IndexOf<TSource>(this IEnumerable<TSource> list, TSource value) where TSource : IEquatable<TSource>
  606. {
  607. return list.IndexOf<TSource>(value, EqualityComparer<TSource>.Default);
  608. }
  609. /// <summary>
  610. /// Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer.
  611. /// </summary>
  612. /// <typeparam name="TSource">The type of the elements of source.</typeparam>
  613. /// <param name="list">A sequence in which to locate a value.</param>
  614. /// <param name="value">The object to locate in the sequence</param>
  615. /// <param name="comparer">An equality comparer to compare values.</param>
  616. /// <returns>The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, –1.</returns>
  617. public static int IndexOf<TSource>(this IEnumerable<TSource> list, TSource value, IEqualityComparer<TSource> comparer)
  618. {
  619. #if (UNITY_IPHONE || UNITY_IOS)
  620. var listArray = list.ToArray();
  621. for (var i = 0; i < listArray.Length; i++)
  622. {
  623. if (comparer.Equals(listArray[i], value))
  624. {
  625. return i;
  626. }
  627. }
  628. #else
  629. int index = 0;
  630. foreach (TSource item in list)
  631. {
  632. if (comparer.Equals(item, value))
  633. {
  634. return index;
  635. }
  636. index++;
  637. }
  638. #endif
  639. return -1;
  640. }
  641. }
  642. }