Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions src/System.Private.CoreLib/src/System/String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,17 +376,31 @@ public static String Join<T>(String separator, IEnumerable<T> values)
using (IEnumerator<T> en = values.GetEnumerator())
{
if (!en.MoveNext())
return String.Empty;

StringBuilder result = StringBuilderCache.Acquire();
return string.Empty;
// We called MoveNext once, so this will be the first item
T currentValue = en.Current;

if (currentValue != null)
// Call ToString before calling MoveNext again, since
// we want to stay consistent with the below loop
// Everything should be called in the order
// MoveNext-Current-ToString, unless further optimizations
// can be made, to avoid breaking changes
string firstString = currentValue?.ToString();

// If there's only 1 item, simply call ToString on that
if (!en.MoveNext())
{
result.Append(currentValue.ToString());
// We have to handle the case of either currentValue
// or its ToString being null
return firstString ?? string.Empty;
}

while (en.MoveNext())
StringBuilder result = StringBuilderCache.Acquire();

result.Append(firstString);

do
{
currentValue = en.Current;

Expand All @@ -396,6 +410,8 @@ public static String Join<T>(String separator, IEnumerable<T> values)
result.Append(currentValue.ToString());
}
}
while (en.MoveNext());

return StringBuilderCache.GetStringAndRelease(result);
}
}
Expand Down