.NET Core 2.1 ile başlayarak string.Create
yöntemi kullanarak bir dizeyi tersine çevirmenin yeni bir yolu vardır .
"Les Mise \ u0301rables", "selbarésiM seL" biçimine dönüştürüleceğinden, bu çözümün Unicode birleştirme karakterlerini vb. Doğru şekilde işlemediğini unutmayın. Diğer cevaplar , daha iyi bir çözüm.
public static string Reverse(string input)
{
return string.Create<string>(input.Length, input, (chars, state) =>
{
state.AsSpan().CopyTo(chars);
chars.Reverse();
});
}
Bu aslında karakterlerini input
yeni bir dizeye kopyalar ve yeni dizeyi yerinde tersine çevirir.
Neden string.Create
faydalı?
Mevcut bir diziden dize oluşturduğumuzda, yeni bir dahili dizi ayrılır ve değerler kopyalanır. Aksi takdirde, bir dizeyi oluşturulduktan sonra (güvenli bir ortamda) değiştirmek mümkün olabilir. Yani, aşağıdaki kod parçasında, biri arabellek, diğeri de dizenin iç dizisi olmak üzere iki kez 10 uzunluğunda bir dizi ayırmamız gerekir.
var chars = new char[10];
// set array values
var str = new string(chars);
string.Create
temelde dize oluşturma süresi boyunca dahili diziyi değiştirmemize izin verir. Bu, artık bir tampona ihtiyacımız yok ve bu nedenle bu char dizisini ayırmaktan kaçınabilir.
Steve Gordon burada daha ayrıntılı olarak yazmıştır . MSDN'de de bir makale var .
Nasıl kullanılır string.Create
?
public static string Create<TState>(int length, TState state, SpanAction<char, TState> action);
Yöntem üç parametre alır:
- Oluşturulacak dizenin uzunluğu,
- yeni dizeyi dinamik olarak oluşturmak için kullanmak istediğiniz veriler,
- ve verilerden son dizeyi oluşturan bir temsilci; burada birinci parametre
char
yeni dizenin iç dizisini gösterir ve ikincisi de geçtiğiniz veri (durum) 'dur string.Create
.
Temsilcinin içinde, yeni dizenin verilerden nasıl oluşturulacağını belirtebiliriz. Bizim durumumuzda, sadece giriş dizesinin karakterlerini Span
yeni dizenin kullandığı yere kopyalarız . Sonra geriSpan
ve böylece tüm dize tersine çevrilir.
Deneyler
Bir dizeyi tersine çevirmek için önerilen yolumu kabul edilen cevapla karşılaştırmak için BenchmarkDotNet'i kullanarak iki kriter yazdım.
public class StringExtensions
{
public static string ReverseWithArray(string input)
{
var charArray = input.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
public static string ReverseWithStringCreate(string input)
{
return string.Create(input.Length, input, (chars, state) =>
{
state.AsSpan().CopyTo(chars);
chars.Reverse();
});
}
}
[MemoryDiagnoser]
public class StringReverseBenchmarks
{
private string input;
[Params(10, 100, 1000)]
public int InputLength { get; set; }
[GlobalSetup]
public void SetInput()
{
// Creates a random string of the given length
this.input = RandomStringGenerator.GetString(InputLength);
}
[Benchmark(Baseline = true)]
public string WithReverseArray() => StringExtensions.ReverseWithArray(input);
[Benchmark]
public string WithStringCreate() => StringExtensions.ReverseWithStringCreate(input);
}
İşte makinemdeki sonuçlar:
| Method | InputLength | Mean | Error | StdDev | Gen 0 | Allocated |
| ---------------- | ----------- | -----------: | ---------: | --------: | -----: | --------: |
| WithReverseArray | 10 | 45.464 ns | 0.4836 ns | 0.4524 ns | 0.0610 | 96 B |
| WithStringCreate | 10 | 39.749 ns | 0.3206 ns | 0.2842 ns | 0.0305 | 48 B |
| | | | | | | |
| WithReverseArray | 100 | 175.162 ns | 2.8766 ns | 2.2458 ns | 0.2897 | 456 B |
| WithStringCreate | 100 | 125.284 ns | 2.4657 ns | 2.0590 ns | 0.1473 | 232 B |
| | | | | | | |
| WithReverseArray | 1000 | 1,523.544 ns | 9.8808 ns | 8.7591 ns | 2.5768 | 4056 B |
| WithStringCreate | 1000 | 1,078.957 ns | 10.2948 ns | 9.6298 ns | 1.2894 | 2032 B |
Gördüğünüz gibi ReverseWithStringCreate
, ReverseWithArray
yöntem tarafından kullanılan belleğin sadece yarısını tahsis ediyoruz .