6

I'm confused which overload string.Split(';') is resolving to; I don't think ';' is a char array is it?

However, this is compiling OK but if I try to add a 2nd StringSplitOptions parameter no appropriate overload is found.

I don't like having to do new char []{';'} is it avoidable?

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • 6
    It **is** a *char array*: `Split(params Char[] value)` – Dmitry Bychenko Oct 14 '15 at 11:10
  • What does the 'params' keyword signify - how is ';' an array? And why is the 2nd version _not_ OK? – Mr. Boy Oct 14 '15 at 11:11
  • 3
    And at least, you can do `new[] { ';' }`. – O. R. Mapper Oct 14 '15 at 11:11
  • 2
    @Mr.Boy: Have you read the [documentation on `params`](https://msdn.microsoft.com/en-us/library/w5zay9db.aspx)? – O. R. Mapper Oct 14 '15 at 11:12
  • 6
    Due to the [`params`](https://msdn.microsoft.com/en-us/library/w5zay9db.aspx) keyword, you can `.Split(';', ',', '-')`. The compiler changes the multiple args into an array – Hans Kesting Oct 14 '15 at 11:12
  • 2
    A `params` parameter also has to be the _last_ one in the signature, and it would be odd passing `StringSplitOptions` before the actual things you want to split on to allow you to create an overload with this signature. You could of course build your own extension method that remaps the parameters the other way round as required. – James Thorpe Oct 14 '15 at 11:14
  • @O.R.Mapper no I've never heard of it. Perhaps that is the answer I'm looking for, how that overload performs differently than the ones taking 2/3 arguments. – Mr. Boy Oct 14 '15 at 11:14
  • Line 933 http://referencesource.microsoft.com/#mscorlib/system/string.cs,1c4a9dc78ba38999 as you can see its a call to internal split with splitoption.none. params is array any way. Thats just for simplification. No performance difference – M.kazem Akhgary Oct 14 '15 at 11:16
  • @O.R.Mapper `new[] { ';' }` is very nice, thanks. Worthy of an answer rather than a comma if you reference the `params` thing too. – Mr. Boy Oct 14 '15 at 11:28
  • @James: I would actually be fine with having `StringSplitOptions` first, as it would seem more analogue to how `string.Format` overloads are defined (and it would allow `params`). – vgru Oct 14 '15 at 11:28
  • @Groo The [official guidance](https://msdn.microsoft.com/en-us/library/ms229015(v=vs.110).aspx) for parameter design says _"**DO** try to order parameters to make it possible to use the params keyword."_ so it wouldn't be out of the question for them to have designed it this way. Guess it's an opinion thing of whether you should be passing "options" as a parameter before the thing being used for the actual work. – James Thorpe Oct 14 '15 at 11:43
  • @James: I agree, it's what `params` mandates anyway, you need to arrange parameters to move the `params` to the last place. I am just saying it's how `string.Format` works, and I am pretty used to using the `string.Format(IFormatProvider culture, string format, params object[] args)` overload. But the funny thing actually is that two different conventions are using in the same BCL class. :) – vgru Oct 14 '15 at 11:53
  • @Groo I don't really see a valid comparison with `String.Format` - as you say the nature of it means `params` has to be last, and it's not like you're passing some sort of option to `String.Format` before the items being worked on - in a way the `params` are the options being used in the format string. Anyway - this is all rather moot and opinion based and a question for the .NET designers as to why `String.Replace` hasn't got an overload for this built in :) – James Thorpe Oct 14 '15 at 12:00

2 Answers2

12

The first overload of String.Split() has parameters defined as

params char[] separator

This means you can pass any number of char parameters and it will work:

someString.Split('1', '2', '3');
// or just one separator
someString.Split(';');

The second overload is different, it defines parameters like this

char[] separator, StringSplitOptions options

Notice, there is no params. Which require you to pass char[] parameter:

someString.Split(new[] {'1', '2', '3'}, StringSplitOptions.None);
// or just one separator
someString.Split(new[] {';'}, StringSplitOptions.None);
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • 2
    I may be doing something wrong here, but my compiler doesn't like the `new {';'}` example. It wants `new []{';'}` instead. – Mels Apr 24 '17 at 14:36
  • This works... and is possibly the dumbest method call in the .net framework for it. Thanks for puzzling this out for us! – Larry Smith Mar 19 '19 at 04:09
1

In the first case you are using this method:

public string[] Split(params char[] separator)

In the second case:

public string[] Split(char[] separator, StringSplitOptions options)

As you can see the declaration in the second case is a little different, so you can't pass parameters in this way.

If you want to use this method in a similar way, you can write your own extension method:

public static class StringExtensions
{
    public static string[] Split(this string s, char separator, StringSplitOptions options)
    {
        return s.Split(new[] { separator }, options);
    }

//or

    public static string[] Split(this string s, StringSplitOptions options, params char[] separator)
    {
        return s.Split(separator, options);
    }
}

And use them like below:

        var s = "asdasd;asd;;";
        var split = s.Split(StringSplitOptions.RemoveEmptyEntries, ';');
        var split2 = s.Split(StringSplitOptions.RemoveEmptyEntries, ';', ',');
        var split3 = s.Split(';', StringSplitOptions.RemoveEmptyEntries);

I suggest you to read more about this elements:

  1. string.Split()
  2. params keyword
  3. params keyword explanations: link

@Groo params keyword explanation:

The docs for params don't actually explain how/when the array gets created, so that's what's probably confusing. The thing is that params is just a hint to the compiler that you are allowed to pass your array's items separated by comma, without explicitly instantiating the array. But a new array containing your parameters is created on each call to the Split method, regardless of whether you are passing 0, 1 or many parameters. Also, you can still create an array yourself and pass it to the method, but this lets the compiler do it for you.

Community
  • 1
  • 1
Pawel Maga
  • 5,428
  • 3
  • 38
  • 62
  • Thanks. Would you add a little information about what `params` does here, to make this a fuller answer for the future? Brief is fine :) – Mr. Boy Oct 14 '15 at 11:24
  • I've added links where you will find more information about this elements. I wont elaborate more about this topic because it is a simple language element that has the appropriate documentation. – Pawel Maga Oct 14 '15 at 11:31
  • 1
    @Mr.Boy: The docs for `params` don't actually explain *how/when* the array gets created, so that's what's probably confusing. The thing is that `params` is just a hint to the compiler that you are allowed to pass your array's items separated by comma, without explicitly instantiating the array. But a new array containing your parameters is created on each call to the `Split` method, regardless of whether you are passing 0, 1 or many parameters. Also, you can still create an array yourself and pass it to the method, but this lets the compiler do it for you. – vgru Oct 14 '15 at 11:56
  • 1
    That comment would make an excellent addition to this answer, if @PawelMaga felt like copy-pasting it in! – Mr. Boy Oct 14 '15 at 12:01