diff --git a/Core/Collections/NativeMemoryEnumerator.cs b/Core/Collections/NativeMemoryEnumerator.cs
new file mode 100644
index 00000000..ed679fa8
--- /dev/null
+++ b/Core/Collections/NativeMemoryEnumerator.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Vanara.Extensions;
+using Vanara.InteropServices;
+
+namespace Vanara.PInvoke.Collections
+{
+ /// Provides a generic enumerator over native memory.
+ /// The type of the element to extract from memory.
+ ///
+ ///
+ public class NativeMemoryEnumerator : UntypedNativeMemoryEnumerator, IEnumerator, IEnumerable
+ {
+ /// Initializes a new instance of the class.
+ /// A pointer to the starting address of a specified number of elements in memory.
+ /// The number of elements to be included in the enumeration.
+ /// Bytes to skip before reading the first element.
+ /// If known, the total number of bytes allocated to the native memory in .
+ /// count
+ ///
+ public NativeMemoryEnumerator(IntPtr ptr, int length, int prefixBytes = 0, SizeT allocatedBytes = default) : base(ptr, typeof(T), length, prefixBytes, allocatedBytes) { }
+
+ /// Gets the element in the collection at the current position of the enumerator.
+ public new T Current => (T)base.Current;
+
+ /// Returns an enumerator that iterates through the collection.
+ /// A that can be used to iterate through the collection.
+ public new IEnumerator GetEnumerator() => this;
+ }
+
+ /// Provides an enumerator over native memory.
+ ///
+ ///
+ public class UntypedNativeMemoryEnumerator : IEnumerator, IEnumerable
+ {
+ /// The number of allocated bytes.
+ protected SizeT allocated;
+
+ /// The number of elements in the enumeration.
+ protected int count;
+
+ /// The index of the current item. (-2) signifies an error. (-1) means MoveNext has not been called..
+ protected int index = -1;
+
+ /// The number of bytes to skip before reading the first element.
+ protected int prefix;
+
+ /// A pointer to the starting address of a specified number of elements in memory.
+ protected IntPtr ptr;
+
+ /// The size of .
+ protected SizeT stSize;
+
+ /// The type of the element to extract from memory.
+ protected Type type;
+
+ /// Initializes a new instance of the class.
+ /// A pointer to the starting address of a specified number of elements in memory.
+ /// The type of the element to extract from memory.
+ /// The number of elements to be included in the enumeration.
+ /// Bytes to skip before reading the first element.
+ /// If known, the total number of bytes allocated to the native memory in .
+ /// count
+ /// type
+ ///
+ public UntypedNativeMemoryEnumerator(IntPtr ptr, Type type, int length, int prefixBytes = 0, SizeT allocatedBytes = default)
+ {
+ if (length < 0 || ptr == IntPtr.Zero && length != 0)
+ throw new ArgumentOutOfRangeException(nameof(length));
+ if (type is null)
+ throw new ArgumentNullException(nameof(type));
+ this.ptr = ptr;
+ count = length;
+ prefix = prefixBytes;
+ allocated = allocatedBytes == default ? (SizeT)uint.MaxValue : allocatedBytes;
+ stSize = InteropExtensions.SizeOf(type);
+ if (allocatedBytes > 0 && stSize * length + prefixBytes > allocatedBytes)
+ throw new InsufficientMemoryException();
+ }
+
+ /// Gets the element in the collection at the current position of the enumerator.
+ public virtual object Current
+ {
+ get
+ {
+ if (index < 0 || index >= count)
+ throw new ArgumentOutOfRangeException(nameof(index));
+ var offset = prefix + index * stSize;
+ return ptr.Offset(offset).Convert(allocated - (uint)offset - (uint)prefix, type);
+ }
+ }
+
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ public virtual void Dispose() { }
+
+ /// Returns an enumerator that iterates through a collection.
+ /// An object that can be used to iterate through the collection.
+ public IEnumerator GetEnumerator() => this;
+
+ /// Advances the enumerator to the next element of the collection.
+ ///
+ /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
+ ///
+ public bool MoveNext()
+ {
+ if (++index >= count)
+ index = -2;
+ return index >= 0;
+ }
+
+ /// Sets the enumerator to its initial position, which is before the first element in the collection.
+ public void Reset() => index = -1;
+ }
+}
\ No newline at end of file
diff --git a/Core/Extensions/InteropExtensions.cs b/Core/Extensions/InteropExtensions.cs
index 5c2d39c7..9b2e4f9f 100644
--- a/Core/Extensions/InteropExtensions.cs
+++ b/Core/Extensions/InteropExtensions.cs
@@ -9,6 +9,7 @@ using System.Security.Permissions;
using Vanara.Extensions.Reflection;
using Vanara.InteropServices;
using Vanara.PInvoke;
+using Vanara.PInvoke.Collections;
namespace Vanara.Extensions
{
@@ -96,6 +97,26 @@ namespace Vanara.Extensions
Marshal.WriteByte(ptr.Offset(ofs), 0, value);
}
+ /// Converts an that points to a C-style array into an .
+ /// Type of native structure used by the C-style array.
+ /// The pointing to the native array.
+ /// The number of items in the native array.
+ /// Bytes to skip before reading the array.
+ /// If known, the total number of bytes allocated to the native memory in .
+ /// An exposing the elements of the native array.
+ public static IEnumerator GetEnumerator(this IntPtr ptr, int count, int prefixBytes = 0, SizeT allocatedBytes = default) =>
+ new NativeMemoryEnumerator(ptr, count, prefixBytes, allocatedBytes);
+
+ /// Converts an that points to a C-style array into an .
+ /// The pointing to the native array.
+ /// Type of native structure used by the C-style array.
+ /// The number of items in the native array.
+ /// Bytes to skip before reading the array.
+ /// If known, the total number of bytes allocated to the native memory in .
+ /// An exposing the elements of the native array.
+ public static System.Collections.IEnumerator GetEnumerator(this IntPtr ptr, Type type, int count, int prefixBytes = 0, SizeT allocatedBytes = default) =>
+ new UntypedNativeMemoryEnumerator(ptr, type, count, prefixBytes, allocatedBytes);
+
///
/// Gets the length of a null terminated array of pointers. This is a very dangerous function and can result in
/// memory access errors if the does not point to a null-terminated array of pointers.
@@ -471,7 +492,7 @@ namespace Vanara.Extensions
/// If known, the total number of bytes allocated to the native memory in .
/// An exposing the elements of the native array.
public static IEnumerable ToIEnum(this IntPtr ptr, int count, int prefixBytes = 0, SizeT allocatedBytes = default) =>
- ToIEnum(ptr, typeof(T), count, prefixBytes, allocatedBytes).Cast();
+ new NativeMemoryEnumerator(ptr, count, prefixBytes, allocatedBytes);
/// Converts an that points to a C-style array into an .
/// The pointing to the native array.
@@ -480,20 +501,8 @@ namespace Vanara.Extensions
/// Bytes to skip before reading the array.
/// If known, the total number of bytes allocated to the native memory in .
/// An exposing the elements of the native array.
- public static IEnumerable