diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml
index 71c8cab22ec3..7abb94cd4cd5 100644
--- a/src/mscorlib/model.xml
+++ b/src/mscorlib/model.xml
@@ -7855,6 +7855,10 @@
+
+
+
+
diff --git a/src/mscorlib/src/System/Text/StringBuilder.cs b/src/mscorlib/src/System/Text/StringBuilder.cs
index f525118fa4b5..e81d90c72281 100644
--- a/src/mscorlib/src/System/Text/StringBuilder.cs
+++ b/src/mscorlib/src/System/Text/StringBuilder.cs
@@ -21,6 +21,7 @@ namespace System.Text {
using System.Threading;
using System.Globalization;
using System.Diagnostics.Contracts;
+ using System.Collections.Generic;
// This class represents a mutable string. It is convenient for situations in
// which it is desirable to modify a string, perhaps by removing, replacing, or
@@ -1011,6 +1012,88 @@ public StringBuilder Append(char[] value) {
return this;
}
+ // Append joined values with a separator between each value.
+ public unsafe StringBuilder AppendJoin(char separator, params T[] values)
+ {
+ // Defer argument validation to the internal function
+ return AppendJoinCore(&separator, 1, values);
+ }
+
+ public unsafe StringBuilder AppendJoin(string separator, params T[] values)
+ {
+ separator = separator ?? string.Empty;
+ fixed (char* pSeparator = separator)
+ {
+ // Defer argument validation to the internal function
+ return AppendJoinCore(pSeparator, separator.Length, values);
+ }
+ }
+
+ public unsafe StringBuilder AppendJoin(char separator, IEnumerable values)
+ {
+ // Defer argument validation to the internal function
+ return AppendJoinCore(&separator, 1, values);
+ }
+
+ public unsafe StringBuilder AppendJoin(string separator, IEnumerable values)
+ {
+ separator = separator ?? string.Empty;
+ fixed (char* pSeparator = separator)
+ {
+ // Defer argument validation to the internal function
+ return AppendJoinCore(pSeparator, separator.Length, values);
+ }
+ }
+
+ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, params T[] values)
+ {
+ if (values == null)
+ throw new ArgumentNullException(nameof(values));
+ Contract.Ensures(Contract.Result() != null);
+
+ if (values.Length == 0)
+ return this;
+
+ var value = values[0];
+ if (value != null)
+ Append(value.ToString());
+
+ for (var i = 1; i < values.Length; i++)
+ {
+ Append(separator, separatorLength);
+ value = values[i];
+ if (value != null)
+ Append(value.ToString());
+ }
+ return this;
+ }
+
+ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, IEnumerable values)
+ {
+ if (values == null)
+ throw new ArgumentNullException(nameof(values));
+ Contract.Ensures(Contract.Result() != null);
+
+ using (var en = values.GetEnumerator())
+ {
+ if (!en.MoveNext())
+ return this;
+
+ var value = en.Current;
+ if (value != null)
+ Append(value.ToString());
+
+ while (en.MoveNext())
+ {
+ Append(separator, separatorLength);
+ value = en.Current;
+ if (value != null)
+ Append(value.ToString());
+ }
+ }
+ return this;
+ }
+
/*====================================Insert====================================
**
==============================================================================*/