LazyReadOnlyCollection.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace SharpCompress
  5. {
  6. internal class LazyReadOnlyCollection<T> : ICollection<T>
  7. {
  8. private readonly List<T> backing = new List<T>();
  9. private readonly IEnumerator<T> source;
  10. private bool fullyLoaded;
  11. public LazyReadOnlyCollection(IEnumerable<T> source)
  12. {
  13. this.source = source.GetEnumerator();
  14. }
  15. private class LazyLoader : IEnumerator<T>
  16. {
  17. private readonly LazyReadOnlyCollection<T> lazyReadOnlyCollection;
  18. private bool disposed;
  19. private int index = -1;
  20. internal LazyLoader(LazyReadOnlyCollection<T> lazyReadOnlyCollection)
  21. {
  22. this.lazyReadOnlyCollection = lazyReadOnlyCollection;
  23. }
  24. #region IEnumerator<T> Members
  25. public T Current => lazyReadOnlyCollection.backing[index];
  26. #endregion
  27. #region IDisposable Members
  28. public void Dispose()
  29. {
  30. if (!disposed)
  31. {
  32. disposed = true;
  33. }
  34. }
  35. #endregion
  36. #region IEnumerator Members
  37. object IEnumerator.Current => Current;
  38. public bool MoveNext()
  39. {
  40. if (index + 1 < lazyReadOnlyCollection.backing.Count)
  41. {
  42. index++;
  43. return true;
  44. }
  45. if (!lazyReadOnlyCollection.fullyLoaded && lazyReadOnlyCollection.source.MoveNext())
  46. {
  47. lazyReadOnlyCollection.backing.Add(lazyReadOnlyCollection.source.Current);
  48. index++;
  49. return true;
  50. }
  51. lazyReadOnlyCollection.fullyLoaded = true;
  52. return false;
  53. }
  54. public void Reset()
  55. {
  56. throw new NotSupportedException();
  57. }
  58. #endregion
  59. }
  60. internal void EnsureFullyLoaded()
  61. {
  62. if (!fullyLoaded)
  63. {
  64. this.ForEach(x => { });
  65. fullyLoaded = true;
  66. }
  67. }
  68. internal IEnumerable<T> GetLoaded()
  69. {
  70. return backing;
  71. }
  72. #region ICollection<T> Members
  73. public void Add(T item)
  74. {
  75. throw new NotSupportedException();
  76. }
  77. public void Clear()
  78. {
  79. throw new NotSupportedException();
  80. }
  81. public bool Contains(T item)
  82. {
  83. EnsureFullyLoaded();
  84. return backing.Contains(item);
  85. }
  86. public void CopyTo(T[] array, int arrayIndex)
  87. {
  88. EnsureFullyLoaded();
  89. backing.CopyTo(array, arrayIndex);
  90. }
  91. public int Count
  92. {
  93. get
  94. {
  95. EnsureFullyLoaded();
  96. return backing.Count;
  97. }
  98. }
  99. public bool IsReadOnly => true;
  100. public bool Remove(T item)
  101. {
  102. throw new NotSupportedException();
  103. }
  104. #endregion
  105. #region IEnumerable<T> Members
  106. //TODO check for concurrent access
  107. public IEnumerator<T> GetEnumerator()
  108. {
  109. return new LazyLoader(this);
  110. }
  111. #endregion
  112. #region IEnumerable Members
  113. IEnumerator IEnumerable.GetEnumerator()
  114. {
  115. return GetEnumerator();
  116. }
  117. #endregion
  118. }
  119. }