Here is my sample code using .NET Core 6:
using System;
namespace testTerminator
{
    class Program
    {
        static void Main(string[] args)
        {
            // Given an array of bytes:
            byte[] array = {72, 101, 108, 108, 111, 0, 0, 32, 72, 101};
            // Converted to a string:
            string data = System.Text.Encoding.ASCII.GetString(array);
            
            // Why does the following line not return the position
            // of the null characters?
            int terminator = data.IndexOf("\0\0");  // returns 0
            // Output:
            Console.WriteLine("Data is '{0}'", data);
            Console.WriteLine("Found terminator at {0}", terminator);
            // Verify null characters are still in the data string:
            byte[] dataBytes = System.Text.Encoding.ASCII.GetBytes(data);
            for (int i = 0; i<dataBytes.Length; i++){
                Console.Write("{0},", dataBytes[i]);
            }
            Console.WriteLine();
        }
    }
}
This results in the following output:
Data is 'Hello He'
Found terminator at 0
72,101,108,108,111,0,0,32,72,101,
Why does the IndexOf("\0\0") return a zero when the null characters are at position 6?
As noted by @AndrewS in the comments, this is documented by Microsoft. The default is to use the CurrentCulture, and it returns 0 if there is an ignored character for that culture. In .Net 5 the Unicode library was changed, which affected this.
Note that you can reproduce this in a simple one-liner:
Console.WriteLine("abc\0".IndexOf("\0"));
To fix this, you need to use an ordinal comparison
int terminator = data.IndexOf("\0\0", StringComparison.Ordinal);  // returns 0
Oddly enough, when you use the char version it doesn't do this
Console.WriteLine("abc\0".IndexOf('\0'));
Returns 3. This is because it does an ordinal comparison by default.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With