Add String.Join overloads accepting a char separator#7942
Conversation
There was a problem hiding this comment.
I kept the parameter names the same as the string-based overloads, so this is value as opposed to values.
There was a problem hiding this comment.
I avoided duplicating the Join(string, object[]) bug where we return "" if the first item is null here.
There was a problem hiding this comment.
@justinvp Unfortunately, this means that it's not possible to share code with the string overload here for now. Ongoing discussion @ https://github.com/dotnet/coreclr/issues/4506#issuecomment-258033970
There was a problem hiding this comment.
You can still share the code - just need a bool argument on what the behavior in this case should be.
There was a problem hiding this comment.
@jkotas, that seems kind of ugly to me. I think it would be better to simply leave things as-is for now, and when fixing the bug is approved then share the code.
There was a problem hiding this comment.
Used checked inside the loop, instead of checking for overflow at the end. 3 2B sized strings for example could overflow enough that the total length goes back to a positive value, so the check seems fairly pointless.
There was a problem hiding this comment.
This will throw OverflowException. Other Join overloads throw OutOfMemory exception in this case...
There was a problem hiding this comment.
Hm, I can change it to do a totalLength < 0 check instead then.
There was a problem hiding this comment.
I happened to see @stephentoub's PR a while ago at #4559, so I mimicked his logic here.
There was a problem hiding this comment.
fixed may/may not have better performance outside the loop, but I think putting it here is best for readability.
There was a problem hiding this comment.
Wouldn't a simple result[copiedLength] = separator be faster?
There was a problem hiding this comment.
@jkotas result is a string, so using a set indexer won't work here.
|
Nice! In the issue over in corefx I said I would add some tests and expose the implementation - I don't actually have time to do this anytime soon, so if you want you can take over |
There was a problem hiding this comment.
Nit: nameof (nameof was just deployed throughout mscorlib). Applies throughout.
|
Any thoughts on sharing code with the |
|
@hughbe Sure, I would be willing to add tests / expose the impl in corefx. |
|
@justinvp Great idea! Esp. considering one of the |
There was a problem hiding this comment.
@justinvp Then pSeparator will be initialized to null. This is technically implementation-defined behavior of Roslyn, but it looks like they're planning to update the spec sometime.
On hindsight, the real issue here looks like separator.Length will nullref if it is null (edit: I just realized, m_firstChar as well)... I'll just add a separator = separator ?? string.Empty beforehand. Thanks for pointing this out.
There was a problem hiding this comment.
This file is no longer being used after the Join char/string impls were unified, so I deleted it.
f649e89 to
1abc87f
Compare
|
Explicit check for overflow may be a bit faster, like: |
|
@jkotas Nice idea. Updated the PR to match. |
There was a problem hiding this comment.
When I added the new Split overloads, I made them all [ComVisible(false)]. I think we should do the same for these new Join overloads.
There was a problem hiding this comment.
Ok edit: See @danmosemsft's comment
There was a problem hiding this comment.
Since you changed String -> string above, maybe go ahead and do the same here.
There was a problem hiding this comment.
I don't know why these overloads are diffing since I didn't change them... but since they are, I guess I might as well format them.
There was a problem hiding this comment.
Should the public unsafe methods be annotated [SecuritySafeCritical] and private JoinCore annotated [SecurityCritical]?
There was a problem hiding this comment.
If I understand @jkotas comment https://github.com/dotnet/corefx/issues/12592#issuecomment-253971384 they are not needed in this assembly as we don't build mscorlib for desktop and the mirror is switched off. @jkotas can confirm.
There was a problem hiding this comment.
Same I think for [ComVisible]. https://github.com/dotnet/corefx/issues/12592#issuecomment-253972687
There was a problem hiding this comment.
Ok, will not add unless someone says otherwise.
There was a problem hiding this comment.
If I understand @jkotas comment dotnet/corefx#12592 (comment) they are not needed in this assembly as we don't build mscorlib for desktop and the mirror is switched off.
I realize that's the case for corefx. I asked because I'm not sure about coreclr given it appears the security annotations are still being maintained here (e.g. #7476). @jkotas should confirm.
There was a problem hiding this comment.
It is not necessary to maintain these anymore.
There was a problem hiding this comment.
I think you can remove the // auto-generated part of the comment.
There was a problem hiding this comment.
@AlexGhiondea There appear to be lots of those comments throughout the repo; if such a change is made it should probably be done in bulk.
There was a problem hiding this comment.
@jamesqo that would work. I was just thinking that since you are adding this method you can clean-up the comment. I am fine with it as-is :).
|
@jkotas, I think this is ready to be merged. |
|
@AlexGhiondea Could you please take care of this? |
|
Looks like the |
|
@jamesqo could you rebase and update the PR so that we can merge this? |
8f794cc to
c60c141
Compare
|
@AlexGhiondea Sure. This is ready for merge now, I believe. |
AlexGhiondea
left a comment
There was a problem hiding this comment.
Thanks for taking care of this!
|
@stephentoub apparently has a couple comments b efore we merge this. |
|
@danmosemsft @stephentoub What are they? |
There was a problem hiding this comment.
It looks like the original author went out of his or her way to keep this check out of this loop. I assume this doesn't make a measurable impact, but have you checked?
There was a problem hiding this comment.
@stephentoub The original version was incorrect in the first place. jointLength < 0 does not tell us whether anything overflowed b/c the int could have wrapped around to negative and passed 0 again, since we're dealing with a variable amount of strings. jointLength + 1 < 0 is also pointless.
There was a problem hiding this comment.
You could check for overflow by doing something like this:
'If (totalLength + currentValue.Length < totalLength)'
There was a problem hiding this comment.
@AlexGhiondea That would have to be in the loop as well; there is no difference from the version that is currently checked in.
There was a problem hiding this comment.
@jamesqo yes, it should still be in the loop but that check would catch overflows even when the value overflows enough to come back into the positive number range.
There was a problem hiding this comment.
@AlexGhiondea, a single int + int cannot overflow that much. Worst case scenario, totalLength and currentValue.Length are both int.MaxValue. Their sum is only -2. It's only when we multiply we run into problems.
There was a problem hiding this comment.
@jamesqo ah yes -- I was thrown off by your comment above about the previous version of the code 😄
* Add String.Join overloads that accept char separators
…7942) * Add String.Join overloads that accept char separators Commit migrated from dotnet/coreclr@3f59c07
This PR adds
string.Joinoverloads that take a char separator, which has been approved by dotnet/corefx#5552. It supplants #7621.Please note that while I've verified the code I've wrote compiles, it's completely untested since I don't have a way to run tests on it. That will be done when the api is exposed in corefx.
Another note: I didn't add a
Join(char, IEnumerable<string>)overload after seeing #7621 (comment) which referred to @stephentoub's comment at #2945 (comment).cc @jkotas @stephentoub @AlexGhiondea @weshaggard @bbowyersmyth @ghost @hughbe