Projelerimizde en çok kullandığımız değişken tipi string olsa gerek. String tipinin reference type ve immutuable olması, projelerde hayli yer alması bizim string değişkenlerle yaptığımız işlemlerde performansa ne kadar dikkat etmemiz gerektiğini gösteriyor.
String immutuable bir değişken tipidir, dedik. Bunun anlamı string bir değişkene verdiğimiz değeri (aslında değerin adresini) asla değiştiremeyiz. Bunu basit bir örnekle açıklamaya çalışalım.
|
string test = "Veri";
//Bir takım işler
test = "Data"; |
Burada yaptığımız heap’de bir yer ayırıp içine “veri”yi koymaktan ve bu yerin adresini test değişkenine vermekten başka bir şey değil. Daha sonra yapılan ise heap’de bir yer daha ayırıp içine “data”yı koymak ve test değişkenine “data”nın adresini vermek. Yani heap’de aslında iki tane yerimiz var (biri “veri”yi içeriyor diğeri “data”yi) ama test değişkenimiz sadece “data”nın bulunduğu adresi tutuyor. Bu şekilde düşündüğümüzde string üzerinde yaptığımız her yeni atamada aslında içindeki veriyi değil, adresini değiştirmiş oluyoruz ve hafızada (heap’de) belki de farkında olmadan fazladan yer tutuyoruz; ta ki garbage collector (GC) zamanı gelip de “veri” nin adresini tutan herhangi bir değişken bulamayıp temizlediği zamana kadar…
Şimdi de bir karşılaştırma örneğine bakalım.
|
string test1 = "veri";
string test2 = "data";
// Bir takım işlemler
if (test1.ToUpper() == test2.ToUpper())
{
// Bir takım işlemler
} |
Proje çıktısının ilgili yerini ILDASM ile inceleyelim:
Görüyoruz ki hafızada test1.ToUpper()’ın sonucu başka bir yerde, test2.ToUpper()’ın sonucu başka bir yerde tanımlanıp farklı değişkenlere alınıyor. (Heap’de “veri”, “data”, “VERİ”, “DATA” yerleri mevcut ve stackda “VERİ”’nin ve “DATA”nın adresini tutan iki ayrı değişken tanımlanmış) Daha sonra da boolean bir değişken tanımlanıp string fonksiyonlarından Equality kullanılarak karşılaştırıldığını görüyoruz. Peki if bloğunu şu şekilde değiştirirsek ne olur acaba, bakalım:
|
if (string.Compare(test1,test2,true) == 0)
{
// Bir takım işlemler
} |
ILDASM ile proje çıktısının ilgili satırına bakarsak:

Fazladan hafızada yer ayırmalar ve değişken tanımlamalar olmamış. Bu da kodumuzun öncekine göre daha performanslı olmasına ve daha az hafıza kullanılmasına sebep olmuştur.
String işlemlerinde sıkça kullandığımız bir başka işlem de birleştirmelerdir. Basit bir örnekle bunu da analiz etmeye çalışalım.
|
string test = "veri1";
//Bir takım işlemler
test += " veri2";
//Bir takım işlemler
test += " veri3"; |

ILDASM çıktısına ve önceki bilgilerimize göre ilk string birleştirmede aslında heapde bir yer ayrılıp içine “veri1 veri2” yazıldığını ve bunun adresini bizim değişkenimizin tuttuğunu görürüz. Benzer şekilde ikinci birleştirme de heap’de “veri1 veri2 veri3” yazan bir yer ayrıldığını ve bunun adresini değişkenimizin tuttuğunu rahatlıkla söyleyebiliriz. (Heap görüntüsü şöyledir: “veri”, veri1 veri2, “veri1 veri2 veri3” Yani hafızada 3 ayrı yer ayrılmıştır.) Yani string değişkenimizin içeriğini aslında değiştiremiyoruz, çünkü kendisi immutuable’dır…
Bu duruma alternatif çözüm StringBuilder sınıfı ile gelmektedir:
|
StringBuilder sb = new StringBuilder();
sb.Append("veri1");
//Bir takım işlemler
sb.Append("veri2");
//Bir takım işlemler
sb.Append("veri3"); |
Aslında her zaman StringBuilder sınıfını kullanmak istenen performansı vermeyecektir. Bu sebeple String birleştirme işlemi belirli bir sayıda ise + veya concat metodunu kullanmak daha faydalı iken, belirsiz ve fazla sayıda string birleştirmeler de StringBuilder sınıfını kullanmak daha iyi olacaktır. Bu tavsiyeyi MSDN’de de görüyoruz:
“The String class is preferable for a concatenation operation if a fixed number of String objects are concatenated. In that case, the individual concatenation operations might even be combined into a single operation by the compiler. A StringBuilder object is preferable for a concatenation operation if an arbitrary number of strings are concatenated; for example, if a loop concatenates a random number of strings of user input.”
Projelerimizin minimum kaynak tüketimi ile maksimum performansta çalışmalarını isteriz. Burada da buna nasıl katkı sağlayacağımızı birkaç string işlemi üzerinde incelemeye çalıştık. Belki onlarca satırdan kazanacağımız birkaç ms ve hafızadan tasarruf edebileceğimiz birkaç byte çok fazla bir fark ettirmeyecektir. Ancak unutulmamalıdır ki projelerdeki satır sayısı arttıkça ve yaptığımız işlemler daha da karmaşıklaştıkça bu tip küçük şeylerin aslında ne denli önemli olduğu ortaya çıkacaktır. Ayrıca .NET Framework mimarisinin nasıl çalıştığını anlamamıza bir o kadar da yardımcı olacaktır.
|