Buradaki cevapların her şeyi kapsadığını düşünmediğim için, burada küçük bir ekleme yapmak istiyorum.
Console.WriteLine(string format, params object[] pars)
çağrıları string.Format
. '+', Dize birleştirmeyi ifade eder. Bunun her zaman stille ilgili olduğunu düşünmüyorum; İçinde bulunduğum bağlama bağlı olarak iki stili karıştırma eğilimindeyim.
Kısa cevap
Karşılaştığınız karar dize tahsisi ile ilgilidir. Basitleştirmeye çalışacağım.
Söyle var
string s = a + "foo" + b;
Bunu yürütürseniz, aşağıdaki gibi değerlendirilecektir:
string tmp1 = a;
string tmp2 = "foo"
string tmp3 = concat(tmp1, tmp2);
string tmp4 = b;
string s = concat(tmp3, tmp4);
tmp
burada gerçekten yerel bir değişken değil, ama JIT için geçici (IL yığınına itildi). Yığına bir dize basarsanız ( ldstr
değişmez değerler için IL'de olduğu gibi ), yığındaki dize işaretçisine bir başvuru koyarsınız.
Her concat
iki dizeyi de içeren herhangi bir dize başvurusu olmadığından, bu başvuruyu çağırdığınız an sorun olur. Bu, .NET'in yeni bir bellek bloğu tahsis etmesi ve ardından iki dizeyle doldurması gerektiği anlamına gelir. Bunun bir problem olmasının nedeni tahsinin nispeten pahalı olmasıdır.
Soru şu şekilde değişir: concat
İşlem sayısını nasıl azaltabilirsiniz ?
Yani, kaba cevap: string.Format
> 1 kat için, '+' 1 kat için iyi çalışır. Ve mikro performans optimizasyonları yapmayı umursamıyorsanız string.Format
, genel durumda iyi çalışır.
Kültür hakkında bir not
Ve sonra kültür denen bir şey var ...
string.Format
CultureInfo
biçimlendirmenizde kullanabilmenizi sağlar . Basit bir operatör '+' mevcut kültürü kullanır.
Bu özellikle dosya formatları ve f.ex yazıyorsanız önemli bir açıklamadır. double
bir dizeye 'eklediğiniz' değerler. Farklı makinelerde, string.Format
açık bir şekilde kullanmazsanız farklı dizelerle karşılaşabilirsiniz CultureInfo
.
F.ex. bir '.' değiştirirseniz ne olacağını düşünün. ',' için virgülle ayrılmış değerler dosyanızı yazarken ... Flemenkçe'de ondalık ayırıcı virgüldür, dolayısıyla kullanıcı 'komik' bir sürpriz yaşayabilir.
Daha ayrıntılı cevap
Önceden dizenin tam boyutunu bilmiyorsanız, kullandığınız arabellekleri genel olarak konumlandırmak için böyle bir ilke kullanmak en iyisidir. Gevşek boşluk önce doldurulur, daha sonra veriler kopyalanır.
Büyüme, yeni bir bellek bloğunun tahsis edilmesi ve eski verilerin yeni tampona kopyalanması anlamına gelir. Daha sonra eski bellek bloğu serbest bırakılabilir. Bu noktada en alt çizgiyi elde edersiniz: büyüme pahalı bir işlemdir.
Bunu yapmanın en pratik yolu, bir genel yerleştirme politikası kullanmaktır. En yaygın politika, arabellekleri 2'nin güçlerinde aşırı konumlandırmaktır. Elbette, bundan biraz daha akıllıca yapmanız gerekir (çünkü 128 karaktere ihtiyacınız olduğunu biliyorsanız 1,2,4,8'den büyümek mantıklı değildir. ) Ama fotoğrafı sen aldın. Politika, yukarıda tarif ettiğim pahalı işlemlerin çoğuna ihtiyaç duymamanızı sağlar.
StringBuilder
"Temel", temelde iki tamponun altında bulunan tamponu aşırı yükleyen bir sınıftır. başlık altında string.Format
kullanır StringBuilder
.
Bu, kararınızı genel-konum-ve-ekleme (-multiple) (w / wo kültürü) arasında ya da sadece tahsis-ve-ekleme arasında temel bir değiş tokuş yapar.
string.Format
herhangi bir kompozit biçimlendirme özellikleri (yani sadece basit{0}
) kullanmaz IL yeniden yazmak bir post-derleme aracı olup olmadığını ve bunları oldukça hızlı dize birleştirme ile değiştirin merak ediyorum . PostSharp gibi mevcut bir IL yeniden yazarıyla böyle bir başarı elde edilebileceğini merak ediyorum.