This commit is contained in:
2026-03-30 12:47:29 +09:00
parent 04dd7222d9
commit 8231d6df60
45 changed files with 2497 additions and 707 deletions

View File

@@ -7,6 +7,9 @@ public unsafe interface IUnsafeCollection : IDisposable
/// <summary>
/// Indicates whether the object has been created. Returns true if the object is created, otherwise false.
/// </summary>
/// <remarks>
/// If ENABLE_DEBUG_LAYER is not defined, this property will only check if the underlying pointer is not null, which may not be sufficient to determine if the collection is fully initialized and ready for use.
/// </remarks>
bool IsCreated
{
get;

View File

@@ -1,6 +1,5 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace Misaki.HighPerformance.LowLevel.Collections;

View File

@@ -1,7 +1,6 @@
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.CompilerServices;
@@ -78,7 +77,9 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
private readonly int _sizeOfTValue;
private readonly int _log2MinGrowth;
#if ENABLE_DEBUG_LAYER
private MemoryHandle _memoryHandle;
#endif
private AllocationHandle _allocationHandle;
public const int MINIMAL_CAPACITY = 64;
@@ -95,6 +96,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
{
get
{
#if ENABLE_DEBUG_LAYER
if (_buffer != null)
{
if (_allocationHandle.IsValid != null)
@@ -108,6 +110,9 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
}
return false;
#else
return _buffer != null;
#endif
}
}
@@ -251,14 +256,22 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
throw new InvalidOperationException("Target allocation handle does not support allocation.");
}
#if ENABLE_DEBUG_LAYER
MemoryHandle memHandle;
var buf = (byte*)_allocationHandle.Alloc(_allocationHandle.State, (uint)totalSize, (nuint)_alignment, allocationOption, &memHandle);
#endif
var buf = (byte*)_allocationHandle.Alloc(_allocationHandle.State, (uint)totalSize, (nuint)_alignment, allocationOption
#if ENABLE_DEBUG_LAYER
, &memHandle
#endif
);
_buffer = buf;
_keys = (TKey*)(_buffer + keyOffset);
_next = (int*)(_buffer + nextOffset);
_buckets = (int*)(_buffer + bucketOffset);
#if ENABLE_DEBUG_LAYER
_memoryHandle = memHandle;
#endif
}
private void ResizeExact(int newCapacity, int newBucketCapacity)
@@ -271,7 +284,9 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
var oldNext = _next;
var oldBuckets = _buckets;
var oldBucketCapacity = _bucketCapacity;
#if ENABLE_DEBUG_LAYER
var oldMemoryHandle = _memoryHandle;
#endif
AllocateBuffer(totalSize, keyOffset, nextOffset, bucketOffset, AllocationOption.None);
_capacity = newCapacity;
@@ -290,7 +305,11 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
if (_allocationHandle.Free != null)
{
_allocationHandle.Free(_allocationHandle.State, oldBuffer, oldMemoryHandle);
_allocationHandle.Free(_allocationHandle.State, oldBuffer
#if ENABLE_DEBUG_LAYER
, oldMemoryHandle
#endif
);
}
}
@@ -705,7 +724,11 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
if (_allocationHandle.Free != null)
{
_allocationHandle.Free(_allocationHandle.State, _buffer, _memoryHandle);
_allocationHandle.Free(_allocationHandle.State, _buffer
#if ENABLE_DEBUG_LAYER
, _memoryHandle
#endif
);
}
_buffer = null;

View File

@@ -143,4 +143,9 @@ public readonly unsafe struct ReadOnlyUnsafeCollection<T> : IEnumerable<T>
{
return _buffer;
}
public static implicit operator ReadOnlySpan<T>(ReadOnlyUnsafeCollection<T> collection)
{
return collection.AsSpan();
}
}

View File

@@ -109,7 +109,7 @@ public unsafe struct UnTypedArray : IUnTypedCollection
return;
}
MemoryHandle memHandle = _memoryHandle;
var memHandle = _memoryHandle;
_buffer = _allocationHandle.Realloc(_allocationHandle.State, _buffer, _size, newSize, _alignment, option, &memHandle);
_size = newSize;
_memoryHandle = memHandle;

View File

@@ -3,9 +3,7 @@ using Misaki.HighPerformance.LowLevel.Collections.Contracts;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.CompilerServices;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Misaki.HighPerformance.LowLevel.Collections;
@@ -26,7 +24,7 @@ internal class UnsafeArrayDebugView<T>
{
var count = _array.Count;
var result = new T[count];
for (int i = 0; i < count; i++)
for (var i = 0; i < count; i++)
{
result[i] = _array[i];
}
@@ -78,7 +76,9 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
private T* _buffer;
private int _count;
#if ENABLE_DEBUG_LAYER
private MemoryHandle _memoryHandle;
#endif
private AllocationHandle _allocationHandle;
public readonly int Count => _count;
@@ -108,6 +108,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
{
get
{
#if ENABLE_DEBUG_LAYER
if (_buffer != null)
{
if (_allocationHandle.IsValid != null)
@@ -121,6 +122,9 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
}
return false;
#else
return _buffer != null;
#endif
}
}
@@ -163,11 +167,19 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
throw new InvalidOperationException("Target allocation handle does not support allocation.");
}
#if ENABLE_DEBUG_LAYER
MemoryHandle memHandle;
var buff = handle.Alloc(handle.State, (nuint)(count * sizeof(T)), AlignOf<T>(), allocationOption, &memHandle);
#endif
var buff = handle.Alloc(handle.State, (nuint)(count * sizeof(T)), AlignOf<T>(), allocationOption
#if ENABLE_DEBUG_LAYER
, &memHandle
#endif
);
_buffer = (T*)buff;
#if ENABLE_DEBUG_LAYER
_memoryHandle = memHandle;
#endif
_allocationHandle = handle;
_count = count;
}
@@ -246,10 +258,18 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
return;
}
#if ENABLE_DEBUG_LAYER
MemoryHandle memHandle = _memoryHandle;
#endif
var elemSize = SizeOf<T>();
_buffer = (T*)_allocationHandle.Realloc(_allocationHandle.State, _buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option, &memHandle);
_buffer = (T*)_allocationHandle.Realloc(_allocationHandle.State, _buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option
#if ENABLE_DEBUG_LAYER
, &memHandle
#endif
);
#if ENABLE_DEBUG_LAYER
_memoryHandle = memHandle;
#endif
_count = newSize;
}
@@ -403,7 +423,11 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
if (_allocationHandle.Free != null)
{
_allocationHandle.Free(_allocationHandle.State, _buffer, _memoryHandle);
_allocationHandle.Free(_allocationHandle.State, _buffer
#if ENABLE_DEBUG_LAYER
, _memoryHandle
#endif
);
}
_buffer = null;

View File

@@ -1,5 +1,4 @@
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
@@ -40,7 +39,7 @@ public unsafe struct UnsafeBitSet : IDisposable, IEquatable<UnsafeBitSet>
private UnsafeBitSet _bitSet;
private int _currentBit;
public Iterator (UnsafeBitSet bitSet)
public Iterator(UnsafeBitSet bitSet)
{
_bitSet = bitSet;
_currentBit = -1;
@@ -116,7 +115,7 @@ public unsafe struct UnsafeBitSet : IDisposable, IEquatable<UnsafeBitSet>
public UnsafeBitSet(Span<uint> bits, Allocator allocator)
{
_bits = new UnsafeArray<uint>(bits.Length, allocator, AllocationOption.None);
_bits.CopyFrom<UnsafeArray<uint>, uint>(bits);
_bits.CopyFrom(bits);
_highestBit = 0;
_max = _bits.Count * (_BIT_SIZE + 1) - 1; // Calculate the maximum index in use
@@ -135,9 +134,9 @@ public unsafe struct UnsafeBitSet : IDisposable, IEquatable<UnsafeBitSet>
}
/// <summary>
/// Determines the required length of an <see cref="UnsafeBitSet"/> to hold the passed id or bit.
/// Determines the required length of an <see cref="UnsafeBitSet"/> to hold the passed ID or bit.
/// </summary>
/// <param name="id">The id or bit.</param>
/// <param name="id">The ID or bit.</param>
/// <returns>A size of required <see cref="uint"/>s for the bitset.</returns>
public static int RequiredLength(int id)
{
@@ -788,14 +787,14 @@ public unsafe struct UnsafeBitSet : IDisposable, IEquatable<UnsafeBitSet>
return !(left == right);
}
public readonly override int GetHashCode()
public override readonly int GetHashCode()
{
var hash = new HashCode();
hash.AddBytes(MemoryMarshal.AsBytes(_bits.AsSpan()));
return hash.ToHashCode();
}
public readonly override string ToString()
public override readonly string ToString()
{
// Convert uint to binary form for pretty printing
var binaryBuilder = new StringBuilder();

View File

@@ -2,7 +2,6 @@ using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections.Contracts;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Misaki.HighPerformance.LowLevel.Collections;

View File

@@ -18,7 +18,7 @@ public unsafe struct UnsafeHashSet<T> : IUnsafeHashCollection<T>, IEnumerable<T>
{
internal HashMapHelper<T>.Enumerator _enumerator;
public readonly T Current => _enumerator.buffer->_keys[_enumerator.index];
public readonly T Current => _enumerator.buffer->_keys[_enumerator.index];
readonly object IEnumerator.Current => Current;
public Enumerator(HashMapHelper<T>* hashMap)

View File

@@ -35,7 +35,7 @@ internal class UnsafeSlotMapDebugView<T>
/// <summary>
/// Provides an unsafe, high-performance slot map for storing and managing unmanaged values, supporting fast insertion,
/// removal, and lookup by slot index and generation.
/// removal, and lookup by slot index and Generation.
/// </summary>
/// <typeparam name="T">The type of value to store in the slot map. Must be unmanaged.</typeparam>
[DebuggerTypeProxy(typeof(UnsafeSlotMapDebugView<>))]
@@ -155,7 +155,7 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
/// Adds the specified item to the collection and returns the index of the slot where it was stored.
/// </summary>
/// <param name="item">The item to add to the collection.</param>
/// <param name="generation">When this method returns, contains the generation number associated with the slot where the item was stored.</param>
/// <param name="generation">When this method returns, contains the Generation number associated with the slot where the item was stored.</param>
/// <returns>The index of the slot in which the item was stored.</returns>
public int Add(T item, out int generation)
{
@@ -184,10 +184,10 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
}
/// <summary>
/// Attempts to remove the item at the specified slot index and generation from the collection.
/// Attempts to remove the item at the specified slot index and Generation from the collection.
/// </summary>
/// <param name="slotIndex">The zero-based index of the slot to remove. Must be within the valid range of slot indices.</param>
/// <param name="generation">The generation value associated with the slot. Removal succeeds only if this matches the current generation of the slot.</param>
/// <param name="generation">The Generation value associated with the slot. Removal succeeds only if this matches the current Generation of the slot.</param>
/// <param name="item">When this method returns, contains the item that was removed if the removal was successful; otherwise, the default value for type <typeparamref name="T"/>.</param>
/// <returns>true if the item was successfully removed; otherwise, false.</returns>
public bool Remove(int slotIndex, int generation, out T item)
@@ -216,10 +216,10 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
}
/// <summary>
/// Attempts to remove the item at the specified slot index and generation from the collection.
/// Attempts to remove the item at the specified slot index and Generation from the collection.
/// </summary>
/// <param name="slotIndex">The zero-based index of the slot to remove. Must be within the valid range of slot indices.</param>
/// <param name="generation">The generation value associated with the slot. Removal succeeds only if this matches the current generation of
/// <param name="generation">The Generation value associated with the slot. Removal succeeds only if this matches the current Generation of
/// the slot.</param>
/// <returns>true if the item was successfully removed; otherwise, false.</returns>
public bool Remove(int slotIndex, int generation)
@@ -228,11 +228,11 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
}
/// <summary>
/// Determines whether the specified slot index contains a valid entry with the given generation.
/// Determines whether the specified slot index contains a valid entry with the given Generation.
/// </summary>
/// <param name="slotIndex">The zero-based index of the slot to check. Must be greater than or equal to 0 and less than the current capacity.</param>
/// <param name="generation">The generation value to compare against the slot's generation.</param>
/// <returns>true if the slot at the specified index is valid and its generation matches the specified value; otherwise, false.</returns>
/// <param name="generation">The Generation value to compare against the slot's Generation.</param>
/// <returns>true if the slot at the specified index is valid and its Generation matches the specified value; otherwise, false.</returns>
public readonly bool Contains(int slotIndex, int generation)
{
if (slotIndex < 0 || slotIndex >= _capacity)
@@ -249,14 +249,14 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
}
/// <summary>
/// Attempts to retrieve the element at the specified slot index and generation.
/// Attempts to retrieve the element at the specified slot index and Generation.
/// </summary>
/// <param name="slotIndex">The zero-based index of the slot to retrieve. Must be within the valid range of slots.</param>
/// <param name="generation">The generation identifier associated with the slot. Used to verify that the slot has not been replaced or
/// <param name="generation">The Generation identifier associated with the slot. Used to verify that the slot has not been replaced or
/// invalidated.</param>
/// <param name="value">When this method returns, contains the element at the specified slot and generation if found; otherwise, the
/// <param name="value">When this method returns, contains the element at the specified slot and Generation if found; otherwise, the
/// default value for type <typeparamref name="T"/>.</param>
/// <returns>true if the element at the specified slot index and generation is found; otherwise, false.</returns>
/// <returns>true if the element at the specified slot index and Generation is found; otherwise, false.</returns>
public readonly bool TryGetElementAt(int slotIndex, int generation, out T value)
{
if (!Contains(slotIndex, generation))
@@ -270,13 +270,13 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
}
/// <summary>
/// Retrieves the element stored at the specified slot index and generation.
/// Retrieves the element stored at the specified slot index and Generation.
/// </summary>
/// <param name="slotIndex">The zero-based index of the slot from which to retrieve the element. Must be within the valid range of allocated slots.</param>
/// <param name="generation">The generation identifier associated with the slot. Used to ensure the element has not been replaced or removed since allocation.</param>
/// <returns>The element of type <see cref="T"/> stored at the specified slot and generation.</returns>
/// <param name="generation">The Generation identifier associated with the slot. Used to ensure the element has not been replaced or removed since allocation.</param>
/// <returns>The element of type <see cref="T"/> stored at the specified slot and Generation.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="slotIndex"/> is less than zero or greater than or equal to the capacity.</exception>
/// <exception cref="InvalidOperationException">Thrown when the specified slot is not occupied or the generation does not match.</exception>
/// <exception cref="InvalidOperationException">Thrown when the specified slot is not occupied or the Generation does not match.</exception>
public readonly T GetElementAt(int slotIndex, int generation)
{
if (!Contains(slotIndex, generation))
@@ -288,13 +288,13 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
}
/// <summary>
/// Returns a reference to the element at the specified slot index and generation, if it exists; otherwise, returns
/// Returns a reference to the element at the specified slot index and Generation, if it exists; otherwise, returns
/// a null reference.
/// </summary>
/// <param name="slotIndex">The zero-based index of the slot to retrieve. Must be within the valid range of allocated slots.</param>
/// <param name="generation">The expected generation value for the slot. Used to verify that the slot has not been recycled or replaced.</param>
/// <param name="exist">When this method returns, contains <see langword="true"/> if a valid element exists at the specified slot and generation; otherwise, <see langword="false"/>.</param>
/// <returns>A reference to the element of type <typeparamref name="T"/> at the specified slot and generation if it exists; otherwise, a null reference.</returns>
/// <param name="generation">The expected Generation value for the slot. Used to verify that the slot has not been recycled or replaced.</param>
/// <param name="exist">When this method returns, contains <see langword="true"/> if a valid element exists at the specified slot and Generation; otherwise, <see langword="false"/>.</param>
/// <returns>A reference to the element of type <typeparamref name="T"/> at the specified slot and Generation if it exists; otherwise, a null reference.</returns>
public ref T GetElementReferenceAt(int slotIndex, int generation, out bool exist)
{
if (!Contains(slotIndex, generation))

View File

@@ -78,7 +78,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
private UnsafeArray<T> _dense;
private UnsafeArray<int> _generations;
private UnsafeArray<int> _sparse;
private UnsafeArray<int> _reverse; // Maps dense index to sparse index. Since this is a general purpose sparse set, we have to include reverse array. In real world ecs, this should be replaced with entity id array.
private UnsafeArray<int> _reverse; // Maps dense index to sparse index. Since this is a general purpose sparse set, we have to include reverse array. In real world ecs, this should be replaced with entity ID array.
private UnsafeStack<int> _freeSparse;
private int _count;
@@ -168,7 +168,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
/// Adds a value to the sparse set and returns a unique sparse index for the value.
/// </summary>
/// <param name="value">The value to add to the sparse set.</param>
/// <param name="generation">Outputs the generation number associated with the added value.</param>
/// <param name="generation">Outputs the Generation number associated with the added value.</param>
/// <returns>A unique sparse index that can be used to reference this value.</returns>
public int Add(T value, out int generation)
{
@@ -205,7 +205,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
/// Removes the value at the specified sparse index.
/// </summary>
/// <param name="sparseIndex">The sparse index of the value to remove.</param>
/// <param name="generation">The generation number associated with the sparse index to validate.</param>
/// <param name="generation">The Generation number associated with the sparse index to validate.</param>
/// <param name="item">When this method returns, contains the item that was removed if the removal was successful; otherwise, the default value for type <typeparamref name="T"/>.</param>
/// <returns>True if the value was removed, false if the sparse index was not found.</returns>
public bool Remove(int sparseIndex, int generation, out T item)
@@ -234,8 +234,8 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
// Mark the sparse index as unused and add to free list
_sparse[sparseIndex] = -1;
_generations[sparseIndex]++; // Increment generation to invalidate old references
_generations[sparseIndex]++; // Increment Generation to invalidate old references
item = _dense[denseIndex];
_freeSparse.Push(sparseIndex);
@@ -248,7 +248,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
/// Removes the value at the specified sparse index.
/// </summary>
/// <param name="sparseIndex">The sparse index of the value to remove.</param>
/// <param name="generation">The generation number associated with the sparse index to validate.</param>
/// <param name="generation">The Generation number associated with the sparse index to validate.</param>
/// <returns>True if the value was removed, false if the sparse index was not found.</returns>
public bool Remove(int sparseIndex, int generation)
{
@@ -275,7 +275,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
// Mark the sparse index as unused and add to free list
_sparse[sparseIndex] = -1;
_generations[sparseIndex]++; // Increment generation to invalidate old references
_generations[sparseIndex]++; // Increment Generation to invalidate old references
_freeSparse.Push(sparseIndex);
_count--;
@@ -287,7 +287,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
/// Checks if the sparse set contains a value at the specified sparse index.
/// </summary>
/// <param name="sparseIndex">The sparse index to check.</param>
/// <param name="generation">The generation number to validate against the stored generation.</param>
/// <param name="generation">The Generation number to validate against the stored Generation.</param>
/// <returns>True if the sparse index is valid and contains a value, false otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool Contains(int sparseIndex, int generation)
@@ -302,10 +302,10 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
}
/// <summary>
/// Gets the value at the specified sparse index and generation.
/// Gets the value at the specified sparse index and Generation.
/// </summary>
/// <param name="sparseIndex">The sparse index to retrieve the value from.</param>
/// <param name="generation">The generation number to validate against the stored generation.</param>
/// <param name="generation">The Generation number to validate against the stored Generation.</param>
/// <param name="value">When this method returns, contains the value at the specified sparse index, if found.</param>
/// <returns>True if the sparse index contains a value, false otherwise.</returns>
public readonly bool TryGetValue(int sparseIndex, int generation, out T value)
@@ -321,10 +321,10 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
}
/// <summary>
/// Gets the value at the specified sparse index and generation.
/// Gets the value at the specified sparse index and Generation.
/// </summary>
/// <param name="sparseIndex">The sparse index to retrieve the value from.</param>
/// <param name="generation">The generation number to validate against the stored generation.</param>
/// <param name="generation">The Generation number to validate against the stored Generation.</param>
/// <returns>The value at the specified sparse index.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the sparse index is not found.</exception>
public readonly T GetValue(int sparseIndex, int generation)
@@ -338,10 +338,10 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
}
/// <summary>
/// Gets reference of the value at the specified sparse index and generation.
/// Gets reference of the value at the specified sparse index and Generation.
/// </summary>
/// <param name="sparseIndex">The sparse index to retrieve the value from.</param>
/// <param name="generation">The generation number to validate against the stored generation.</param>
/// <param name="generation">The Generation number to validate against the stored Generation.</param>
/// <param name="exist">Outputs whether the sparse index exists in the set.</param>
/// <returns>Reference of the value at the specified sparse index.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the sparse index is not found.</exception>
@@ -361,7 +361,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
/// Updates the value at the specified sparse index.
/// </summary>
/// <param name="sparseIndex">The sparse index of the value to update.</param>
/// <param name="generation">The generation number to validate against the stored generation.</param>
/// <param name="generation">The Generation number to validate against the stored Generation.</param>
/// <param name="value">The new value.</param>
/// <returns>True if the value was updated, false if the sparse index was not found.</returns>
public bool SetValue(int sparseIndex, int generation, T value)

View File

@@ -23,7 +23,7 @@ internal class UnsafeStackDebugView<T>
{
var items = new T[_stack.Count];
var pItems = (T*)_stack.GetUnsafePtr();
for (int i = 0; i < _stack.Count; i++)
for (var i = 0; i < _stack.Count; i++)
{
items[i] = pItems[i];
}