-
-
Save dadhi/7e6d10bdc75a5d3e2ea83344dbc6312a to your computer and use it in GitHub Desktop.
Fixed stack/heap array with any element type
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
var list1 = new FixedList<string, Buffer16<string>>(); | |
var list2 = new FixedList<string, Buffer32<string>>(); | |
UseList(ref list1, "Hello"); | |
UseList(ref list2, "World"); | |
Console.WriteLine(list1.GetRef(0)); | |
Console.WriteLine(list2.GetRef(0)); | |
static void UseList<TItem, TList>(ref TList list, TItem item) | |
where TList : IFixedList<TItem> | |
{ | |
list.Add(item); | |
} | |
public interface IFixedList<T> | |
{ | |
int Count { get; } | |
ref T GetRef(int index); | |
void Add(T item); | |
} | |
public struct FixedList<TElement, TBuffer> : IFixedList<TElement> | |
where TBuffer : struct, IBuffer<TElement> | |
{ | |
private TBuffer _buffer; | |
private TElement[] _heapBuffer; | |
private int _count; | |
public int Count => _count; | |
public ref TElement GetRef(int index) | |
{ | |
// CheckIndex | |
return ref _heapBuffer != null | |
? ref _heapBuffer[index] | |
: ref _buffer.GetRef(index); | |
} | |
public void Add(TElement item) | |
{ | |
if (_heapBuffer == null && _buffer.Count > _count) | |
{ | |
_buffer.GetRef(_count++) = item; | |
return; | |
} | |
_heapBuffer ??= new TElement[16]; | |
// Reallocate heap buffer if needed | |
_heapBuffer[_count++] = item; | |
} | |
} | |
public interface IBuffer<T> | |
{ | |
int Count { get; } | |
ref T GetRef(int index); | |
} | |
[InlineArray(16)] | |
public struct Buffer16<T> : IBuffer<T> | |
{ | |
private T _element0; | |
public int Count => 16; | |
public ref T GetRef(int index) => ref MemoryMarshal.CreateSpan(ref _element0, Count)[index]; | |
} | |
[InlineArray(32)] | |
public struct Buffer32<T> : IBuffer<T> | |
{ | |
private T _element0; | |
public int Count => 32; | |
public ref T GetRef(int index) => ref MemoryMarshal.CreateSpan(ref _element0, Count)[index]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment