Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit dd74fca

Browse files
justinvpstephentoub
authored andcommitted
Use string.Create in BitConverter.ToString(byte[]) (#15218)
Avoids unnecessary allocations and copying, and reduces the amount of unsafe code.
1 parent a7ad29d commit dd74fca

File tree

1 file changed

+17
-42
lines changed

1 file changed

+17
-42
lines changed

src/mscorlib/shared/System/BitConverter.cs

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -354,17 +354,6 @@ public static double ToDouble(ReadOnlySpan<byte> value)
354354
return Unsafe.ReadUnaligned<double>(ref value.DangerousGetPinnableReference());
355355
}
356356

357-
private static char GetHexValue(int i)
358-
{
359-
Debug.Assert(i >= 0 && i < 16, "i is out of range.");
360-
if (i < 10)
361-
{
362-
return (char)(i + '0');
363-
}
364-
365-
return (char)(i - 10 + 'A');
366-
}
367-
368357
// Converts an array of bytes into a String.
369358
public static string ToString(byte[] value, int startIndex, int length)
370359
{
@@ -388,41 +377,27 @@ public static string ToString(byte[] value, int startIndex, int length)
388377
throw new ArgumentOutOfRangeException(nameof(length), SR.Format(SR.ArgumentOutOfRange_LengthTooLarge, (int.MaxValue / 3)));
389378
}
390379

391-
int chArrayLength = length * 3;
392-
const int StackLimit = 512; // arbitrary limit to switch from stack to heap allocation
393-
unsafe
380+
return string.Create(length * 3 - 1, (value, startIndex, length), (dst, state) =>
394381
{
395-
if (chArrayLength < StackLimit)
396-
{
397-
char* chArrayPtr = stackalloc char[chArrayLength];
398-
return ToString(value, startIndex, length, chArrayPtr, chArrayLength);
399-
}
400-
else
401-
{
402-
char[] chArray = new char[chArrayLength];
403-
fixed (char* chArrayPtr = &chArray[0])
404-
return ToString(value, startIndex, length, chArrayPtr, chArrayLength);
405-
}
406-
}
407-
}
382+
const string HexValues = "0123456789ABCDEF";
408383

409-
private static unsafe string ToString(byte[] value, int startIndex, int length, char* chArray, int chArrayLength)
410-
{
411-
Debug.Assert(length > 0);
412-
Debug.Assert(chArrayLength == length * 3);
384+
var src = new ReadOnlySpan<byte>(state.value, state.startIndex, state.length);
413385

414-
char* p = chArray;
415-
int endIndex = startIndex + length;
416-
for (int i = startIndex; i < endIndex; i++)
417-
{
418-
byte b = value[i];
419-
*p++ = GetHexValue(b >> 4);
420-
*p++ = GetHexValue(b & 0xF);
421-
*p++ = '-';
422-
}
386+
int i = 0;
387+
int j = 0;
388+
389+
byte b = src[i++];
390+
dst[j++] = HexValues[b >> 4];
391+
dst[j++] = HexValues[b & 0xF];
423392

424-
// We don't need the last '-' character
425-
return new string(chArray, 0, chArrayLength - 1);
393+
while (i < src.Length)
394+
{
395+
b = src[i++];
396+
dst[j++] = '-';
397+
dst[j++] = HexValues[b >> 4];
398+
dst[j++] = HexValues[b & 0xF];
399+
}
400+
});
426401
}
427402

428403
// Converts an array of bytes into a String.

0 commit comments

Comments
 (0)