ArraySegment basit olarak yine bir array’in belirli bir bölümünü temsil eden bir struct. Bu yapıyı Span’den farklı olarak bir wrapper olarak düşünebiliriz. ArraySegment aynı zamanda ICollection, IEnumerable, IList, IReadOnlyCollection, IReadOnlyList interfacelerini de implemente ediyor.
Varolan bir array üzerinde bir ArraySegment’i şu şekilde yaratabiliriz.
var array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; ArraySegment<int> segment = new ArraySegment<int>(array, 2, 3); //segment : 3,4,5
ArraySegment yaratırken kullandığımız parametreler orjinal arrayin kendisi, segmentin hangi offsetten başlayacağı ve ne kadar uzunlukta olacağı. ArraySegmenti yarattıktan sonra o tip üzerinden orjinal arraye, offset ve uzunluk değerlerine de ulaşmak mümkün.
var array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; ArraySegment<int> segment = new ArraySegment<int>(array, 2, 3); //segment : 3,4,5 Console.WriteLine(segment.Offset); //2 Console.WriteLine(segment.Count); //3 Console.WriteLine(segment.Array.Length); //10
ArraySegment içerisinde bulunan Array propertysi her zaman orjinal array’i gösterir. Yani ArraySegment kullanarak array üzerinde yaptığınız işlemler doğrudan orjinal array üzerinde yapılır. Bunu gözönünde bulundurmamızda fayda var. Eğer böyle olmasını istemiyorsanız arrayin bir kopyasını alıp ilerlemeniz gerekir.
var array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; ArraySegment<int> segment = new ArraySegment<int>(array, 2, 3); //segment : 3,4,5 segment[0] = 10; Console.Write(array[2]); //10 ArraySegment'in en önemli özelliklerinden biri de LINQ querylerini çalıştırabiliyor olmamız. var array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; ArraySegment<int> segment = new ArraySegment<int>(array, 2, 3); ////segment : 3,4,5 Console.WriteLine(segment.Max()); //5 ArraySegment'de de Span ve Memory tipleri gibi slicingi supportu bulunmakta. var array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; ArraySegment<int> segment = new ArraySegment<int>(array, 2, 3); ////segment : 3,4,5 var newSegment = segment.Slice(1, 1); //newSegment: 4
İki ArraySegment instance’ının aynı olabilmesi için aynı arrayi göstermeleri, aynı offsetten başlamaları ve eşiş sayıda eleman içermeleri gerekiyor.
StringSegment
StringSegment tipi de aynı ArraySegment’te olduğu stringin farklı bölgelerini belirten bir struct. Bu structı kullanarak string.Substring metodunu kullanmadan string üzerindeki belirli bir bölge üzerinde işlem yapabiliriz. Böylece yeni bir string yaratarak allocationa neden olmadan işlemleri gerçekleştirebiliriz.
string sample = "test:0:stringsegment"; StringSegment first = new StringSegment(sample, 0, sample.IndexOf(':')); //first: test StringSegment last = new StringSegment(sample, sample.LastIndexOf(':') + 1, sample.Length - sample.LastIndexOf(':') - 1); //last:stringsegment
Bu tip de yine ArrayString gibi slicingi desteklemekte. Bunun için StringSegment.SubSegment metodunu kullanabiliriz.
string sample = "test:0:stringsegment"; StringSegment last = new StringSegment(sample, sample.LastIndexOf(':') + 1, sample.Length - sample.LastIndexOf(':') - 1); //last:stringsegment StringSegment segment = last.Subsegment(6); //segment:segment
Evet gördüğümüz üzere ArraySegment ve StringSegment, array ve string üzerindeki belirli alanlarda çalışabilmek için kullanabileceğimiz tiplerden bir tanesi. Bu tipleri kullanarak örneğin arrayin belirli bölgelerinde multithread olarak çalışma yapmamız mümkün. Aynı zamanda async metotlarda da kullanabiliyoruz. Span ve memory’den farkları nedir diye baktığımızda ise hatırlarsanız span ve memory birden fazla tipteki memory bölgelerinde çalışabiliyordu. String ve ArraySegment ise sadece array ve string üzerinde çalışabiliyor.
Eğer sadece array veya string ile çalışacaksanız ve bu tipler üzerinde parsing veya bu tiplerin farklı bölümlerini multithread olarak işleme gibi işlemler yapacaksanız bu tipleri kullanabilirsiniz.
Örneğin ASP.NET Core içerisinde headerların parsing işleminde aspnetcore/MediaTypeHeaderValue.cs at main · dotnet/aspnetcore (github.com) doğrudan StringSegment’in kullanıldığını görebilirsiniz. Böylece parsing esnasında hiçbir şekilde gereksiz string üretimi gerçekleştirilmiyor ve etkin bir implementasyon yapılıyor.