ArrayUtil.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.CompilerServices;
  5. namespace Cysharp.Threading.Tasks.Internal
  6. {
  7. internal static class ArrayUtil
  8. {
  9. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  10. public static void EnsureCapacity<T>(ref T[] array, int index)
  11. {
  12. if (array.Length <= index)
  13. {
  14. EnsureCore(ref array, index);
  15. }
  16. }
  17. // rare case, no inlining.
  18. [MethodImpl(MethodImplOptions.NoInlining)]
  19. static void EnsureCore<T>(ref T[] array, int index)
  20. {
  21. var newSize = array.Length * 2;
  22. var newArray = new T[(index < newSize) ? newSize : (index * 2)];
  23. Array.Copy(array, 0, newArray, 0, array.Length);
  24. array = newArray;
  25. }
  26. /// <summary>
  27. /// Optimizing utility to avoid .ToArray() that creates buffer copy(cut to just size).
  28. /// </summary>
  29. public static (T[] array, int length) Materialize<T>(IEnumerable<T> source)
  30. {
  31. if (source is T[] array)
  32. {
  33. return (array, array.Length);
  34. }
  35. var defaultCount = 4;
  36. if (source is ICollection<T> coll)
  37. {
  38. defaultCount = coll.Count;
  39. var buffer = new T[defaultCount];
  40. coll.CopyTo(buffer, 0);
  41. return (buffer, defaultCount);
  42. }
  43. else if (source is IReadOnlyCollection<T> rcoll)
  44. {
  45. defaultCount = rcoll.Count;
  46. }
  47. if (defaultCount == 0)
  48. {
  49. return (Array.Empty<T>(), 0);
  50. }
  51. {
  52. var index = 0;
  53. var buffer = new T[defaultCount];
  54. foreach (var item in source)
  55. {
  56. EnsureCapacity(ref buffer, index);
  57. buffer[index++] = item;
  58. }
  59. return (buffer, index);
  60. }
  61. }
  62. }
  63. }