59

Consider this code:

var x = "tesx".Remove('x');

If I run this code, I get this exception:

startIndex must be less than length of string.

Why can I pass a char instead of an int to this method? Why don't I get a compilation error?

enter image description here

Why does the compiler have this behavior?

Dariusz Woźniak
  • 9,640
  • 6
  • 60
  • 73

6 Answers6

95

you try to remove 'x' which is a declared as char, x is equal to 120

The .Remove only takes 2 parameters of type int the start and (optional) count to remove from the string.

If you pass a char, it will be converted to the integer representation. Meaning if you pass 'x' -> 120 is greater than the string's .Length and that's why it will throw this error!

MichaC
  • 13,104
  • 2
  • 44
  • 56
  • 56
    To clarify, this is a design decision made in the C# language that it considers `char` to be implicitly convertible to `int` (a remnant of C). – Joey Oct 13 '13 at 10:14
  • ... aided by the design decision to do access checks as part of overload resolution. This makes it pointless to define a private `.Remove(Char)`. – MSalters Oct 14 '13 at 17:21
27

Implicit conversion lets you compile this code since char can be converted to int and no explicit conversion is required. This will also compile and the answer will be 600 (120*5) -

        char c = 'x';
        int i = c;
        int j = 5;
        int answer = i * j;

From MSDN, implicit conversion is summarized as below -

Implicit conversion

As other's have stated you could use Replace or Remove with valid inputs.

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
22

There is no overload of Remove that takes a char, so the character is implicitly converted to an int and the Remove method tries to use it as an index into the string, which is way outside the string. That's why you get that runtime error instead of a compile time error saying that the parameter type is wrong.

To use Remove to remove part of a string, you first need to find where in the string that part is. Example:

var x = "tesx";
var x = x.Remove(x.IndexOf('x'), 1);

This will remove the first occurance of 'x' in the string. If there could be more than one occurance, and you want to remove all, using Replace is more efficient:

var x = "tesx".Replace("x", String.Empty);
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Why we can pass char instead int? –  Oct 13 '13 at 10:13
  • @ShahroozJefriㇱ Of course, There is a implicit conversion from `char` to `int` – Sriram Sakthivel Oct 13 '13 at 10:15
  • 1
    @ShahroozJefriㇱ: Some types can be implicitly converted to other types, for example a `byte` can be used when an `int` value is needed. A `char` is also implicitly convertable to an `int` which is handy in some cases, but can also be confusing as in this case. – Guffa Oct 13 '13 at 10:17
9

Remove takes an int parameter for the index within the string to start removing characters, see msdn. The remove call must automatically convert the char to its ASCII integer index and try to remove the character at that index from the string, it is not trying to remove the character itself.

If you just want to remove any cases where x occurs in the string do:

"testx".Replace("x",string.Empty);

If you want to remove the first index of x in the string do:

var value = "testx1x2";
var newValue = value.Remove(value.IndexOf('x'), 1);
gmn
  • 4,199
  • 4
  • 24
  • 46
  • Originally the answer suggested `.Replace('x', '');` which won't compile. It's since been corrected. – p.s.w.g Oct 13 '13 at 10:09
  • Not my downvote but Remove and Replace is different. Replace replaces all the occurences, this semantically does different thing – Sriram Sakthivel Oct 13 '13 at 10:17
  • I suggested Replace because it appears that semantically that's exactly what is trying to be achieved when calling remove with 'x'. If I called remove with a character I'd expect all instances of that character to be removed from the string. – gmn Oct 13 '13 at 10:21
2

Since you are passing a char in the function and this value is getting converted to int at runtime hence you are getting the runtime error because the value of char at runtime is more than the length of the string.You may try like this:-

var x = "tesx";
var s = x.Remove(x.IndexOf('x'), 1);

or

var s = x.Replace("x",string.Empty);

.Remove takes the int as parameter. Remove takes two parameters. The first one is what position in your string you want to start at. (The count starts at zero.) The second parameter is how many characters you want to delete, starting from the position you specified.

On a side note:

From MSDN:

This method(.Remove) does not modify the value of the current instance. Instead, it returns a new string in which the number of characters specified by the count parameter have been removed. The characters are removed at the position specified by startIndex.

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
-1

You can use extension methods to create your own methods for already existing classes. Consider following example:

using System;
using MyExtensions;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            const string str1 = "tesx";
            var x = str1.RemoveByChar('x');
            Console.WriteLine(x);
            Console.ReadKey();
        }
    }
}

namespace MyExtensions
{
    public static class StringExtensions
    {
        public static string RemoveByChar(this String str, char c)
        {
            return str.Remove(str.IndexOf(c), 1);
        }
    }
}
Mayur Agarwal
  • 124
  • 1
  • 8