UnmanagedArray 非托管数组,可随时释放内存
由于在C# 里提供的 int[] array = new int[1000000]; 这样的数组,其内存释放很难由程序员完全控制,在申请一个大数组后,程序可能会变得很慢。
/// <summary>
///元素类型为sbyte, byte, char, short, ushort, int, uint, long, ulong, float, double, decimal, bool 或其它struct的非托管数组
/// 可随时释放内存
/// </summary>
/// <typeparam name="T">sbyte, byte, char, short, ushort, int, uint, long, ulong, float, double, decimal, bool或其它struct, 不能使用enum类型作为T</typeparam>
public class UnmanagedArray<T> : UnmanagedArrayBase where T : struct
{
/// <summary>
/// 元素类型为sbyte, byte, char, short, ushort, int, uint, long, ulong, float, double, decimal, bool 或其它struct的非托管数组
/// </summary>
/// <param name="count"></param>
[MethodImpl(MethodImplOptions.Synchronized)]
public UnmanagedArray(int count) : base(count, Marshal.SizeOf(typeof(T)))
{
}
/// <summary>
/// 获取或设置索引为<paramref name="index"/>的元素
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public T this[int index]
{
get
{
if (index < 0 || index >= Count)
{
throw new IndexOutOfRangeException("index of UnmanagedArray is out of range");
}
var pItem = Header + (index * _elementSize);
T rslt = Marshal.PtrToStructure<T>(pItem);
return rslt;
}
set
{
if (index < 0 || index >= Count)
{
throw new IndexOutOfRangeException("index of UnmanagedArray is out of range");
}
var pItem = Header + (index * _elementSize);
Marshal.StructureToPtr<T>(value, pItem, true);
}
}
/// <summary>
/// 按索引顺序依次获取各个元素
/// </summary>
/// <returns></returns>
public IEnumerable<T> GetElements()
{
if (!this._disposed)
{
for (int i = 0; i < Count; i++)
{
yield return this[i];
}
}
}
}
public abstract class UnmanagedArrayBase : IDisposable
{
/// <summary>
/// 数组指针
/// </summary>
public IntPtr Header { get; private set; }
/// <summary>
/// 元素数目
/// </summary>
public int Count { get; private set; }
/// <summary>
/// 申请到的字节数
/// </summary>
public int ByteLength
{
get { return this.Count * this._elementSize; }
}
/// <summary>
/// 单个元素的字节数
/// </summary>
protected int _elementSize;
protected static readonly List<IDisposable> _allocatedArrays = new List<IDisposable>();
/// <summary>
/// 非托管数组
/// </summary>
/// <param name="elementCount">元素数目</param>
/// <param name="elementSize">单个元素的字节数</param>
[MethodImpl(MethodImplOptions.Synchronized)]
protected UnmanagedArrayBase(int elementCount, int elementSize)
{
Count = elementCount;
_elementSize = elementSize;
int memSize = elementCount * elementSize;
Header = Marshal.AllocHGlobal(memSize);
_allocatedArrays.Add(this);
}
/// <summary>
/// 立即释放所有<see cref="UnmanagedArray"/>
/// </summary>
[MethodImpl(MethodImplOptions.Synchronized)]
public static void FreeAll()
{
foreach (var item in _allocatedArrays)
{
item.Dispose();
}
_allocatedArrays.Clear();
}
~UnmanagedArrayBase()
{
Dispose();
}
#region IDisposable
protected bool _disposed;
protected void Dispose(bool disposiing)
{
if (_disposed)
{
return;
}
if (disposiing)
{
// 托管类型清理
}
IntPtr ptr = this.Header;
if (ptr != IntPtr.Zero)
{
Count = 0;
Header = IntPtr.Zero;
Marshal.FreeHGlobal(ptr);
}
_disposed = true;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
public static class UnmanagedArrayExtend
{
/// <summary>
/// 获取非托管数组的第一个元素的地址
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public static unsafe void* FirstElement(this UnmanagedArrayBase array)
{
var header = (void*)array.Header;
return header;
}
/// <summary>
/// 获取非托管数组的最后一个元素的地址再向后一个单位的地址
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public static unsafe void* TailAddress(this UnmanagedArrayBase array)
{
var tail = (void*)(array.Header + array.ByteLength);
return tail;
}
}