10

In C# if I want to split a string by another string I have to do something like that :

testString.Split(new string[] { "anotherString" }, StringSplitOptions.None);

From the overloaded String.Split MSDN Documentation we can see the implementation and why such a call has to be made.

Coming from Python, It is hard for me to understand correctly why such a call is needed. I mean I could use Regex.Split to get a similar syntax than the Python's implementation but I would have to do it at the cost of less performance (setup time) for anything simple.

So basically, my question is why the hell can't we just do:

testString.Split("anotherString");

Note that I'm not suggesting any prototype nor implementation. I understand why you couldn't implement the above version considering the current API. My goal was to understand why such an API could have been created considering the benefit that the above syntax brings. As of now, flexibility seems to be the goal of the current String.Split which make sense, but to be honest I really thought there was some sort of performance gain somewhere. I guess I was wrong.

  • 3
    I was thinking about this too. My speculation is that they just didn't put much effort into designing this one API. And if they realized their mistake, it was too late. – Euphoric Jun 8 '18 at 14:30
  • @Caleth Can you elaborate on this. maybe I'm wrong but I don't see what's ambiugous about it. Why can't I do testString.Split(",.;"); and testString.Split(new Char [] {',', '.', ';',); which are not the same thing. – scharette Jun 8 '18 at 14:42
  • @Euphoric I tought so too, but that would be so odd. Hope someone comes with a more logic answer. – scharette Jun 8 '18 at 14:44
  • You can iterate over a string just like an IEnumerable<char> so the additional prototype you are suggesting might appear ambiguous in certain cases (do you delimit by the whole string or delimit by each of its characters?) Just a guess. – John Wu Jun 9 '18 at 2:05
  • @JohnWu Maybe it is a personal thing, But for 99.9% of occurrences of syntax like testString.Split("anotherString");, I'm pretty confident to say that the expected behavior was to delimit on the whole string (anotherString in this case). – scharette Jun 11 '18 at 12:05
15

Sometimes splitting on more than one char/string is useful, so the API allows you to provide an array, giving you maximum flexibility. In the case of chars, you get both simplity of syntax and flexibility since the parameter is marked as params so you can write Split('x') rather than Split(new[]{'x'}).

So why is there not a similar option for strings, allowing you to write Split("x")?

This is perhaps an unfortunate consequence of how the API is designed. Initially it only allowed splitting on chars. Spliting on strings was added in 2.0, probably because it is more complex to implement. But it was not possible to add String.Split(string) or String.Split(string[]) overloads, since this would make the expression testString.Split(null) ambiguous and this code would not compile anymore.

testString.Split(null) is actually a pretty common idiom since it splits the string on whitespace, so such breakage would be too widespread to be acceptable.

Using a null-parameter as a switch for special behavior is generally considered bad design these days, so I think it is fair to say this API is just flawed.

There is no Split(string[], Int32) either, probably for a similar reason - it would be ambiguous with Split(char[], Int32) if the first parameter is null. There are similar overloads with the StringSplitOptions parameters, but these were all added at the same time in 2.0, so no ambiguity was introduced in existing code.

Note

To be clear, this is just my hypothesis, I don't know the actual thinking by the .net framework designers.

  • 1
    Well, is that at all useful? Doubt that. And it is only an API-break, not an ABI one. – Deduplicator Jun 8 '18 at 18:45
  • 2
    @Deduplicator: Split(null) splits on whitespace, so it is probably one of the most common use cases for split, even though it is bad API design to use a null like this. – JacquesB Jun 8 '18 at 18:54
  • 1
    I think @Deduplicator wanted to say that Split(null) is useless if you allow Split(""). Besides the fact that it would allow a way better syntax, the latter is more verbose anyway... – scharette Jun 8 '18 at 20:27
  • 1
    @scharette: Sure, but it is not possible to change now, without breaking backward compatibility. – JacquesB Jun 8 '18 at 20:30
  • 1
    a note: with the current C# 8 preview, by turning off base types nullability String.Split(null) would no longer be ambiguous, so they could add the overload – BgrWorker Jun 12 '18 at 15:29
2

Not being the author of the methods, I do not know why that set of overloads was chosen. However, there are two things to note here:

  1. If you are splitting on a single character, then the public string[] Split(params char[] separator) version can be used thus:

    var splitValues = testString.Split(',');
    

    as the char[] is a params parameter.

  2. You can easily add your own extension method here to achieve what you want:

    public static class StringExtensions
    {
        public static string[] Split(this string source, string separator)
            => source.Split(new string[] { separator }, StringSplitOptions.None);
    }
    

    and now testString.Split("anotherString"); will work for you.

  • 1
    Thanks for the feedback. Although your answer is helpful and concise, I can't agree with you. Especially the second point. Isn't one more reason to have it built-in ? All it does is let the community create different version of a method that everyone (or almost everyone) expect to behave the same way. – scharette Jun 8 '18 at 15:13
  • Not trying to debate by the way, your point is entirely valid. Just trying to understand the reason behind this. Logically there must be a historical or performance reason... – scharette Jun 8 '18 at 15:14
  • @scharette: The reason is to make the method as general purpose as possible. As preferable as you find your chosen method signature, it won't work for multiple delimiters. Microsoft's version will work for multiple delimiters as well as your single delimiter. – Robert Harvey Jun 8 '18 at 16:59
  • @RobertHarvey Well wouldn't both be possible? Let's say the extension method in the above answer was part of String class, both would be possible. Am I wrong ? – scharette Jun 8 '18 at 17:02
  • I think you're missing the point. Your overload only allows one delimiter. Microsoft's overload allows more than one. You can't call your overload multiple times and achieve the same result; that's not how this works. – Robert Harvey Jun 8 '18 at 17:04
1

Different languages have somewhat different rules for implicit conversions and overloading, and the .NET Framework is designed to be usable with any of them. In the Option Strict Off dialect of VB.NET, a value of type String may be passed to a function which expects a Char[] with behavior equivalent to calling ToCharArray() on the string.

I think the sensible thing to do would have been to have separate names for Split (which accepts a single Char or String) and SplitMulti (which would accept a Char[] or String[]), but .NET sometimes seems to favor using overloading alone to pick different kinds of operations. Unfortunately, I know of no way to use String.Split to accommodate any usage scenarios that would require distinguishing different kinds of delimiters other than by splitting separately on each.

Another omission is an option to preserve delimiters, either including them at the end of the preceding string, or at the start of the following string, or having odd-numbered array elements be delimiters while even-numbered elements are the things between them.

  • 1
    .NET sometimes seems to favor using overloading alone to pick different kinds of operations. So true... – scharette Jun 8 '18 at 20:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.