diff --git a/src/System.Runtime/ref/System.Runtime.cs b/src/System.Runtime/ref/System.Runtime.cs index 6ec8c8d61059..62b9417776d2 100644 --- a/src/System.Runtime/ref/System.Runtime.cs +++ b/src/System.Runtime/ref/System.Runtime.cs @@ -2156,6 +2156,7 @@ public String(System.ReadOnlySpan value) { } public bool Contains(string value, StringComparison comparisonType) { throw null; } public static System.String Copy(System.String str) { throw null; } public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { } + public static string Create(int length, TState state, System.Buffers.SpanAction action) { throw null; } public bool EndsWith(char value) { throw null; } public bool EndsWith(string value) { throw null; } public bool EndsWith(System.String value, bool ignoreCase, System.Globalization.CultureInfo culture) { throw null; } @@ -3857,6 +3858,11 @@ public abstract class OwnedMemory : IDisposable, IRetainable protected internal abstract bool TryGetArray(out ArraySegment arraySegment); } } +namespace System.Buffers +{ + public delegate void SpanAction(Span span, TArg arg); + public delegate void ReadOnlySpanAction(ReadOnlySpan span, TArg arg); +} namespace System.Collections { [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] diff --git a/src/System.Runtime/tests/System/StringTests.netcoreapp.cs b/src/System.Runtime/tests/System/StringTests.netcoreapp.cs index 9cb554590ea7..f2a5039afa2e 100644 --- a/src/System.Runtime/tests/System/StringTests.netcoreapp.cs +++ b/src/System.Runtime/tests/System/StringTests.netcoreapp.cs @@ -32,6 +32,64 @@ public static void Ctor_CharSpan(char[] valueArray, int startIndex, int length, Assert.Equal(expected, new string(span)); } + [Fact] + public static void Create_InvalidArguments_Throw() + { + AssertExtensions.Throws("action", () => string.Create(-1, 0, null)); + AssertExtensions.Throws("length", () => string.Create(-1, 0, (span, state) => { })); + } + + [Fact] + public static void Create_Length0_ReturnsEmptyString() + { + bool actionInvoked = false; + Assert.Same(string.Empty, string.Create(0, 0, (span, state) => actionInvoked = true)); + Assert.False(actionInvoked); + } + + [Fact] + public static void Create_NullState_Allowed() + { + string result = string.Create(1, (object)null, (span, state) => + { + span[0] = 'a'; + Assert.Null(state); + }); + Assert.Equal("a", result); + } + + [Fact] + public static void Create_ClearsMemory() + { + const int Length = 10; + string result = string.Create(Length, (object)null, (span, state) => + { + for (int i = 0; i < span.Length; i++) + { + Assert.Equal('\0', span[i]); + } + }); + Assert.Equal(new string('\0', Length), result); + } + + [Theory] + [InlineData("a")] + [InlineData("this is a test")] + [InlineData("\0\u8001\u8002\ufffd\u1234\ud800\udfff")] + public static void Create_ReturnsExpectedString(string expected) + { + char[] input = expected.ToCharArray(); + string result = string.Create(input.Length, input, (span, state) => + { + Assert.Same(input, state); + for (int i = 0; i < state.Length; i++) + { + span[i] = state[i]; + } + }); + Assert.Equal(expected, result); + } + [Theory] // CurrentCulture [InlineData("Hello", "ello", StringComparison.CurrentCulture, true)]