Search code examples
c#linqchecksumcrc

Problem with Convert.ToInt32 and getting error Index and length must refer to a location within the string


We want get crc code from a string. for example: string is (ff03c1) and crc code is (3d).

The bellow code works correctly until the string is less than 186 characters. sample string:

20000F38080000D1080020110800190D0000000000000000000000000000000020000F38080000D1080020110800190D000000000000000000000000000000020000F38080000D1080020110800190D000000000000000000000000000

But this string not working (187 characters):

20000F38080000D1080020110800190D0000000000000000000000000000000020000F38080000D1080020110800190D000000000000000000000000000000020000F38080000D1080020110800190D000000000000000000000000000**0**

error: Index and length must refer to a location within the string. Parameter name: length

public static string CreateCRCCode(string Value)
{
    return Enumerable.Range(0, Value.Length)
                     .Where(x => x % 2 == 0)
                     .Select(x => Convert.ToInt32(Value.Substring(x, 2), 16))
                     .Aggregate((i, i1) => i ^ i1)
                     .ToString("X");
}

how we can use string more than 186 character?


Solution

  • Root cause

    The real problem is not with the 186 or 187 characters, the problem is the odd and even, what I tried to say is, you will get the same error for an input of 200 as well. The reason is that,

    • Consider that the Value = "200" so, Value.Length = 3 and hence Enumerable.Range(0, Value.Length) will gives you 0,1,2.
    • After applying .Where(x => x % 2 == 0) the collection became 0,2.

    • So when applying the substring(Value.Substring(x, 2)) it will search for the substring starts at index 2 and off length 2(in the second iteration) which is not a valid index. That causes the error.

    Proposed Fix:

    • I don't get any reason for applying Where(x => x % 2 == 0) in the given snippet, if it is necessary please cross check the conditions and scenarios.
    • Change the Enumerable.Range based on the collection length like the following:

      Enumerable.Range(0, Value.Length % 2 == 0 ? Value.Length : Value.Length-1)