Skip to content

Commit

Permalink
Remove char[] allocations from RegistryKey and List copy to Array (#7…
Browse files Browse the repository at this point in the history
…8737)

* Avoid redondant verification EnsureNotDisposed() already called by SubKeyCount & ValueCount.

* Replace List by string[] to avoid List.ToArray() copy (it must handle rare cases where there are more or less elements during the loop).

* Apply suggestions from code review

Co-authored-by: Stephen Toub <stoub@microsoft.com>
  • Loading branch information
Poppyto and stephentoub committed Dec 5, 2022
1 parent 3855a99 commit d47a24c
Showing 1 changed file with 21 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -784,24 +784,24 @@ public static RegistryKey FromHandle(SafeRegistryHandle handle, RegistryView vie
/// <returns>All subkey names.</returns>
public string[] GetSubKeyNames()
{
EnsureNotDisposed();
int subkeys = SubKeyCount;

if (subkeys <= 0)
{
return Array.Empty<string>();
}

List<string> names = new List<string>(subkeys);
Span<char> name = stackalloc char[MaxKeyLength + 1];
string[] names = new string[subkeys];
Span<char> nameSpan = stackalloc char[MaxKeyLength + 1];

int result;
int nameLength = name.Length;
int nameLength = nameSpan.Length;
int cpt = 0;

while ((result = Interop.Advapi32.RegEnumKeyEx(
_hkey,
names.Count,
ref MemoryMarshal.GetReference(name),
cpt,
ref MemoryMarshal.GetReference(nameSpan),
ref nameLength,
null,
null,
Expand All @@ -811,17 +811,29 @@ ref MemoryMarshal.GetReference(name),
switch (result)
{
case Interop.Errors.ERROR_SUCCESS:
names.Add(new string(name.Slice(0, nameLength)));
nameLength = name.Length;
if (cpt >= names.Length) // possible new item during loop
{
Array.Resize(ref names, names.Length * 2);
}

names[cpt++] = new string(nameSpan.Slice(0, nameLength));
nameLength = nameSpan.Length;
break;

default:
// Throw the error
Win32Error(result, null);
break;
}
}

return names.ToArray();
// Shrink array to fit found items, if necessary
if (cpt < names.Length)
{
Array.Resize(ref names, cpt);
}

return names;
}

/// <summary>Retrieves the count of values.</summary>
Expand Down Expand Up @@ -858,8 +870,6 @@ public int ValueCount
/// <returns>All value names.</returns>
public unsafe string[] GetValueNames()
{
EnsureNotDisposed();

int values = ValueCount;

if (values <= 0)
Expand Down

0 comments on commit d47a24c

Please sign in to comment.