Skip to content

Commit a08cfcb

Browse files
authored
* Registry.GetSubKeyNames : Remove List copy to Array (#79345)
* * Replace List by string[] to avoid List.ToArray() copy (it must handle rare cases where there are more or less elements during the loop). * // Shrink array to fit found items, if necessary
1 parent 64187f4 commit a08cfcb

File tree

1 file changed

+23
-5
lines changed
  • src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32

1 file changed

+23
-5
lines changed

src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ public unsafe string[] GetValueNames()
877877
return Array.Empty<string>();
878878
}
879879

880-
var names = new List<string>(values);
880+
string[] names = new string[values];
881881

882882
// Names in the registry aren't usually very long, although they can go to as large
883883
// as 16383 characters (MaxValueLength).
@@ -888,6 +888,7 @@ public unsafe string[] GetValueNames()
888888
// only if needed.
889889

890890
char[]? name = ArrayPool<char>.Shared.Rent(100);
891+
int cpt = 0;
891892

892893
try
893894
{
@@ -896,7 +897,7 @@ public unsafe string[] GetValueNames()
896897

897898
while ((result = Interop.Advapi32.RegEnumValue(
898899
_hkey,
899-
names.Count,
900+
cpt,
900901
name,
901902
ref nameLength,
902903
0,
@@ -909,7 +910,12 @@ public unsafe string[] GetValueNames()
909910
// The size is only ever reported back correctly in the case
910911
// of ERROR_SUCCESS. It will almost always be changed, however.
911912
case Interop.Errors.ERROR_SUCCESS:
912-
names.Add(new string(name, 0, nameLength));
913+
if (cpt >= names.Length) // possible new item during loop
914+
{
915+
Array.Resize(ref names, names.Length * 2);
916+
}
917+
918+
names[cpt++] = new string(name, 0, nameLength);
913919
break;
914920
case Interop.Errors.ERROR_MORE_DATA:
915921
if (IsPerfDataKey())
@@ -919,9 +925,15 @@ public unsafe string[] GetValueNames()
919925
// to be big enough however. 8 characters is the largest
920926
// known name. The size isn't returned, but the string is
921927
// null terminated.
928+
929+
if (cpt >= names.Length) // possible new item during loop
930+
{
931+
Array.Resize(ref names, names.Length * 2);
932+
}
933+
922934
fixed (char* c = &name[0])
923935
{
924-
names.Add(new string(c));
936+
names[cpt++] = new string(c);
925937
}
926938
}
927939
else
@@ -949,7 +961,13 @@ public unsafe string[] GetValueNames()
949961
ArrayPool<char>.Shared.Return(name);
950962
}
951963

952-
return names.ToArray();
964+
// Shrink array to fit found items, if necessary
965+
if (cpt < names.Length)
966+
{
967+
Array.Resize(ref names, cpt);
968+
}
969+
970+
return names;
953971
}
954972

955973
/// <summary>Retrieves the specified value. <b>null</b> is returned if the value doesn't exist</summary>

0 commit comments

Comments
 (0)