Skip to content

[API Proposal] add ReadOnlySpan<byte> overloads to BitConverter.ToString()  #50588

Closed as not planned

Description

@Symbai

Background and Motivation

BitConverter.ToString() has no overloads to accept Readonlyspan. When we got a span we have to call ToArray() first. Other BitConverter functions do have a Readonlyspan overload, such as BitConverter.ToInt32().

Proposed API

namespace System
{
    public class BitConverter {
+        public static string ToString(ReadOnlySpan<byte> value);
     }

Usage Examples

ReadOnlySpan<byte> span = BitConverter.GetBytes("hello world").AsSpan();
Console.WriteLine(BitConverter.ToString(span));

Activity

  1. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Apr 1, 2021
  2. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Apr 1, 2021
  3. GrabYourPitchforks commented on Apr 1, 2021

    @GrabYourPitchforks
    Member

    FYI we don't normally add startIndex and length parameters on APIs which take spans. The caller is expected to slice the span appropriately before calling the method.

    Do you have a usage example where you're relying on BitConverter.ToString in your own code? The example you provided won't compile, even with the APIs you had proposed here.

  4. Symbai commented on Apr 1, 2021

    @Symbai
    Author

    Yes I do have but I cannot show it public. However I can show you a variation of it:

    const int infoLength = 32;
    byte[] infoStartingBytes = { 0xFF, 0xFF, 0xFF, 0xFF };
    
    ReadOnlySpan<byte> span = System.IO.File.ReadAllBytes("C:\\data.dat").AsSpan();
    int pos = span.IndexOf(infoStartingBytes);
    
    while (pos != -1) {
    	span = span.Slice(span.IndexOf(infoStartingBytes));
    	int id = BitConverter.ToInt32(span);
    	span = span.Slice(infoLength + 1);
    	string name = System.Text.Encoding.UTF8.GetString(span);
    	span = span.Slice(infoLength + 1);
    	// couple of lines later
    	string hash = BitConverter.ToString(span.Slice(infoLength).ToArray());
    	span = span.Slice(infoLength + 1);
    	// saving these information somewhere
    	pos = span.IndexOf(infoStartingBytes);
    }

    Using a span has the benefit of slicing. However at one point I have to convert it back to an array when I want to use BitConverter.ToString. I wouldn't mind if there is no overload with startIndex and length parameters since this can easily applied to the span instead but I want to get rid of the additional extra allocation of ToArray(). And I asked myself why every other function of BitConverter has received a span overload but not ToString?

  5. GrabYourPitchforks commented on Apr 1, 2021

    @GrabYourPitchforks
    Member

    Thanks! I'll mark this ready for review.

  6. added
    api-ready-for-reviewAPI is ready for review, it is NOT ready for implementation
    and removed
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Apr 1, 2021
  7. stephentoub commented on Apr 1, 2021

    @stephentoub
    Member

    Having the dashes between each byte is important to your use case?

  8. stephentoub commented on Apr 1, 2021

    @stephentoub
    Member

    Just want to point out that the details of the format used, dashes or not, casing, etc. was debated at length in #17837, and the decision then was to just add Convert.ToHexString that only offered the one approach of no separators, all upper-case.

  9. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    and removed
    api-ready-for-reviewAPI is ready for review, it is NOT ready for implementation
    on Apr 1, 2021
  10. 1 remaining item

  11. stephentoub commented on Apr 2, 2021

    @stephentoub
    Member

    we shouldn't change the behavior.

    I'm not suggesting changing behavior. Convert.ToHexString already takes a span and produces a hex string, just without dashes. I was questioning whether we need another.

  12. XArtur0 commented on Jun 17, 2021

    @XArtur0

    I'm not suggesting changing behavior. Convert.ToHexString already takes a span and produces a hex string, just without dashes. I was questioning whether we need another.

    So, all of us that do require the dash* have to either change our logic (not just code), roll our own hex formatter or keep allocating (and copying) memory on the heap? Don't get me wrong, all 3 are fair, its not like our existing code got broken...
    I agree that #17837 is a better forward solution, I will probably end up changing my code to use it instead myself.

    If no overload is added, perhaps BitConverter.ToString should be decorated with [Obsolete("Use Convert.ToHexString where possible")] so developers that remove the '-' easily realize they don't have to anymore =].

    *I personally kept the dash because didn't want the performance hit of removing them.

  13. removed
    untriagedNew issue has not been triaged by the area owner
    on Jul 12, 2021
  14. modified the milestones: 7.0.0, Future on Jul 12, 2021
  15. msschl commented on Aug 25, 2021

    @msschl

    I'm not suggesting changing behavior. Convert.ToHexString already takes a span and produces a hex string, just without dashes. I was questioning whether we need another.

    Well in my use case, I use the BitConverter.ToString method to print the hex string to the console for debug purposes. Having dashes keeps the string more readable for me. I often have to write some thing along this just for debugging:

    Console.WriteLine(BitConverter.ToString(reader.ReadBytes(reader.BytesRemaining).ToArray()));

    where reader.ReadBytes(numOfBytes) returns a ReadOnlySpan<byte>

    I personally would appreciate adding this api.

  16. Symbai commented on Feb 28, 2026

    @Symbai
    Author

    Comment

  17. tannergooding commented on Apr 3, 2026

    @tannergooding
    Member

    Closing this as not planned.

    As per the above, this was already debated extensively in a past API review and we opted to not go this route. There's not enough interest in this specific API and the overwhelming majority are using the APIs on Convert instead which don't involve any separator. Users who really need this and who cannot just use the existing byte[] value, int startIndex, int length overload can always copy the 20-30 lines of code required.

  18. locked and limited conversation to collaborators on May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions