Skip to content

Commit 1b1f461

Browse files
committed
Use bool[] to check index validity
1 parent ec10b38 commit 1b1f461

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

DictionaryList/DictionaryList.cs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Linq;
45
using System.Runtime.CompilerServices;
56

67
namespace Vectorial1024.Collections.Generic
@@ -27,6 +28,8 @@ internal DataBox(TData value)
2728

2829
internal List<DataBox<TValue>?> _list = new List<DataBox<TValue>?>();
2930

31+
internal bool[] _issetLookup;
32+
3033
internal int _actualCount;
3134

3235
// the version of the DictionaryList, to ensure the enumerator can work correctly
@@ -37,6 +40,8 @@ internal DataBox(TData value)
3740
/// </summary>
3841
public DictionaryList()
3942
{
43+
var capacity = Capacity;
44+
_issetLookup = new bool[capacity];
4045
}
4146

4247
/// <summary>
@@ -48,6 +53,7 @@ public DictionaryList(DictionaryList<TValue> collection)
4853
{
4954
_list = new List<DataBox<TValue>?>(collection._list);
5055
_actualCount = collection._actualCount;
56+
_issetLookup = (bool[]) collection._issetLookup.Clone();
5157
}
5258

5359
/// <summary>
@@ -57,6 +63,7 @@ public DictionaryList(DictionaryList<TValue> collection)
5763
public DictionaryList(int capacity)
5864
{
5965
_list = new List<DataBox<TValue>?>(capacity);
66+
_issetLookup = new bool[capacity];
6067
}
6168

6269
/// <summary>
@@ -88,6 +95,7 @@ public TValue this[int index]
8895
set
8996
{
9097
_list[index] = new DataBox<TValue>(value);
98+
_issetLookup[index] = true;
9199
}
92100
}
93101

@@ -98,9 +106,17 @@ public TValue this[int index]
98106
[MethodImpl(MethodImplOptions.AggressiveInlining)]
99107
public void Add(TValue value)
100108
{
109+
var nextIndex = _list.Count;
101110
_list.Add(new DataBox<TValue>(value));
102111
_actualCount++;
103112
_version++;
113+
114+
// react to resizing if happened
115+
if (_issetLookup.Length != _list.Capacity)
116+
{
117+
Array.Resize(ref _issetLookup, _list.Capacity);
118+
}
119+
_issetLookup[nextIndex] = true;
104120
}
105121

106122
/// <summary>
@@ -120,6 +136,7 @@ public void UnsetAt(int index)
120136

121137
_list[index] = null;
122138
_actualCount--;
139+
_issetLookup[index] = false;
123140
}
124141

125142
/// <summary>
@@ -139,7 +156,15 @@ public bool ContainsIndex(int index)
139156
return false;
140157
}
141158
// we might have it
142-
return _list[index].HasValue;
159+
return IndexIsSet(index);
160+
}
161+
162+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
163+
internal bool IndexIsSet(int index)
164+
{
165+
// does not check for index range, for internal use where we are very sure it does not cause range overflow
166+
// we force-inline it to waive this method call
167+
return _issetLookup[index];
143168
}
144169

145170
#region CompactAndTrim
@@ -151,6 +176,7 @@ public void Clear()
151176
{
152177
_list.Clear();
153178
_actualCount = 0;
179+
_issetLookup = new bool[Capacity];
154180
}
155181

156182
/// <summary>
@@ -172,6 +198,7 @@ public void CompactAndTrimExcess()
172198
_list = newList;
173199
_actualCount = newList.Count;
174200
_version++;
201+
_issetLookup = Enumerable.Repeat(true, _actualCount).ToArray();
175202
}
176203

177204
#endregion
@@ -185,6 +212,7 @@ internal struct DictionaryListEnumerator : IEnumerator<KeyValuePair<int, TValue>
185212
private KeyValuePair<int, TValue> _current;
186213
private readonly int _size;
187214
private readonly int _version;
215+
private readonly bool[] _issetLookup;
188216

189217
internal DictionaryListEnumerator(DictionaryList<TValue> dictList)
190218
{
@@ -193,6 +221,7 @@ internal DictionaryListEnumerator(DictionaryList<TValue> dictList)
193221
_current = default;
194222
_size = _dictList._list.Count;
195223
_version = dictList._version;
224+
_issetLookup = _dictList._issetLookup;
196225
}
197226

198227
public bool MoveNext()
@@ -201,7 +230,7 @@ public bool MoveNext()
201230
var theDictList = _dictList;
202231
while (_version == theDictList._version && (uint)iterIndex < (uint)_size)
203232
{
204-
if (!theDictList.ContainsIndex(iterIndex))
233+
if (!theDictList.IndexIsSet(iterIndex))
205234
{
206235
// not set; find the next one!
207236
iterIndex++;

0 commit comments

Comments
 (0)