C # 'da dize ve tamsayı değişkenlerini birleştirirken .ToString () kullanmalı mıyım?


19
int a = 1;
int b = 2;
int sum = a + b;
string expression = "Expression: " + a + " + " + b + " = " + sum;
Console.WriteLine(expression); //displays Expression 1 + 2 = 3

Kullanmalı mıyım:

string expression = "Expression: " + a + " + " + b + " = " + sum;

veya

string expression = "Expression: " + a.ToString() + " + " + b.ToString() + " = " + result.ToString();

ToString()Birleştirirken kullanılması tavsiye edilir mi stringve int?


6
Gelen a + "" + b + ""veya "" + a + b + "", hiç önemli değil: hepsi dize birleştirme var. İçinde a + b + ""önemli: ave bönce eklenir.
Tim S.

4
Yan not: VB.NET'te, açık bir dize birleştirme operatörüne sahip olarak bu belirsizlikten kaçınılır : "Expression: " + abir derleme zamanı hatası atar (Option Strict On ile), "Expression: " & adize birleştirme gerçekleştirir.
Heinzi

İlk kod boks (Int32 int) ile sonuçlanır, ikincisi değil. İkincisi daha hızlı.
Rasgele Alfabe

Yanıtlar:


33

ToString kullanım

Hayır, ToStringburada kullanmamalısın .

Dize birleştirmesi, dizeleri otomatik olarak dizelere dönüştürmez; bu, iki değişkeninizin neredeyse aynı olduğu anlamına gelir:

İşlenenlerden biri veya her ikisi de dize türünde olduğunda, önceden tanımlanmış toplama işleçleri işlenenlerin dize olarak temsil edilenlerini birleştirir.

Kaynak: C # Dil Özellikleri: Toplama operatörü, MSDN .

Öte yandan, birincisi (olmadan ToString):

  • Yazmak daha kısa,
  • Okumak daha kısa,
  • Bakımı daha kolaydır ve:
  • yazarın amacını tam olarak gösterir: dizeleri birleştirmek.

İlkini tercih edin.

Kaputun altında

İlginç olan, kaputun altında neler olduğunu görmek. Bunu görmenin yollarından biri, LINQPad içindeki IL kodunu izlemek. Bu program:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = a + b;
    Console.WriteLine(c);
}

aşağıdaki IL'ye çevrilir:

IL_0001:  ldc.i4.3    
IL_0002:  stloc.0     // a
IL_0003:  ldstr       " Hello"
IL_0008:  stloc.1     // b
IL_0009:  ldloc.0     // a
IL_000A:  box         System.Int32
IL_000F:  ldloc.1     // b
IL_0010:  call        System.String.Concat
IL_0015:  stloc.2     // c
IL_0016:  ldloc.2     // c
IL_0017:  call        System.Console.WriteLine

Gördün System.String.Concatmü? Bu, orijinal kodun tam olarak aynı IL'ye dönüşen şekilde de yazılabileceği anlamına gelir:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = string.Concat(a, b); // This is the line which was changed.
    Console.WriteLine(c);
}

Belgelerinistring.Concat(object[]) okuduğunuzda şunları öğrenebilirsiniz:

Yöntem her bir nesne birleştirir args parametresiz çağırarak ToStringbu nesnenin bir yöntem; herhangi bir sınırlayıcı eklemez.

Bu ToStringgereksiz demektir . Ayrıca:

String.Empty dizideki boş nesnelerin yerine kullanılır.

Hangi bazı işlenenlerin null olduğu durumu güzelce ele alır (bkz. Dipnot 1).

Son örnekte, birleştirme tercüme edildiğinde string.Concat, derleyici optimizasyonlarını da vurgulamak gerekir:

var a = "Hello " + "World";

şu dile çevrilmiştir:

ldstr       "Hello World"
stloc.0

Diğer yandan:

var a = string.Concat("Hello ", "World");

şu dile çevrilmiştir:

ldstr       "Hello "
ldstr       "World"
call        System.String.Concat
stloc.0

Diğer alternatifler

Elbette C # 'da nesnelerin dize temsillerini birleştirmek için başka yollar vardır.

  1. StringBuilderçok fazla birleştirme işlemi yapmanız gerektiğinde kullanılır ve oluşturulan ara dizelerin sayısını azaltmaya yardımcı olur. Bir StringBuilderveya sıradan bir birleştirme kullanmanız gerektiğine karar vermek kolay olmayabilir. Bir profil oluşturucu kullanın veya Yığın Taşması ile ilgili cevapları arayın.

    Kullanmanın StringBuilder, kodun okunmasını ve bakımını zorlaştırmanın büyük bir dezavantajı vardır. Sorunuzdaki basit durumlar için, StringBuilderyalnızca kodun okunabilirliği için değil, aynı zamanda performans açısından da yararsızdır.

  2. string.Join sınırlayıcı eklemeniz gerektiğinde kullanılmalıdır.

    Açıkçası, string.Joindizeleri birleştirmek için asla boş bir ayırıcıyla kullanmayın .

  3. string.Formatdize birleştirme işlemine dize şablonlaması tercih edildiğinde kullanılabilir. Tercih edebileceğiniz durumlardan biri, mesajın kunthet tarafından yanıtlandığı şekilde yerelleştirilebildiği durumlardır.

    Kullanmanın string.Format, sizinki gibi basit durumlar için uygun olmayan birkaç dezavantajı vardır:

    • Basit "{0}" yer tutucuları ile, hangi parametrenin nereye gittiğine dair genellikle belirsizdir. Parametreleri yanlışlıkla tersine çevirmek veya unutmak sık görülür. Neyse ki, C # 6 nihayet bu sorunu çözen dize enterpolasyonunu tanıttı .

    • Çalışma zamanı performansı düşebilir. Tabii ki, düşünmeyin string.Formatolduğu zaman daha yavaş. Performans önemliyse, iki yaklaşımı ölçün ve varsayımlar yerine gerçek sonuçlarınıza göre hangisinin daha hızlı olduğunu belirleyin.

    • Kodun yazılması biraz daha uzun, okunması daha uzun ve bakımı daha zordur, ancak bu son derece küçüktür ve sizi çok fazla rahatsız etmemelidir.


¹ Fark, nesnelerden biri olduğunda görünür null. Olmadan ToString, a nullboş bir dize ile değiştirilir. İle ToStringa NullReferenceExceptionatılır.


1
Tam olarak bu nedenle (öngörülemeyen davranış), dizeleri ile birleştirmek +çoğu dilde kötü uygulama olarak kabul edilir. Bu durumda kullanırım string.Concat, birçok durumda string.Formatdaha iyidir. Kullanmak kesinlikle Pythonic değildir +ve PEP 3101'in %de lehine olması cesaret kırıcıdır str.format.
Arda Xi

2
Boş bir dizenin yerine nullgerçekten "güzelce işlemek" mi? Eh, "sonraki hata özgeçmiş üzerinde" kadar kötü değil ...
Deduplicator

Kaputun altında, .ToString () öğesini çağırmadan bitiştirirseniz, boks gerçekleşir ... ve Concat(object[])yerine kullanılır Concat(string[]). Yani "string " + iaslında aynı değil"string " + i.ToString()
Rasgele Alfabe

@RandomAlphabets: geçerli nokta. Bununla birlikte, fark basitçe ToString(): OP kodunun bir durumda, System.String.Concatdiğer durumda uygulanmasıdır. Dolayısıyla, cevap geçerli kalır: faydası olmayan kodu yazmayın.
Arseni Mourzenko

15

Bunun yerine, dize biçimlendirici kullanmalısınız. Numaranızı dize ile temsil veya yerelleştirmeyle biçimlendirmek daha kolaydır. Örneğin:

string expression = string.Format("Expression: {0} + {1} = {2}", a, b, sum);

MSDN hakkında daha fazla bilgi .

Bununla birlikte, dize biçimlendirici dize birleştirme işleminden daha az okunabilir (ve belki de performans).


6
Bu seçeneğin neden daha iyi olduğunu açıklamak ister misiniz?
Dünya Mühendisi

@WorldEngineer: Açıklamayı güncelledim.
kunthet

12
Başkalarını bilmiyorum, ama aslında bunu daha okunabilir buluyorum. Belki de C [ile büyüdüğüm için s [n] printf bu tür kodlar için tek gerçekçi seçenektir.
Jules

2
Ama bu şekilde bir yerine üç hata kaynağı var. Dizeye bir şey eklediğinizde, 1) biçim dizesini değiştirmek zorundasınız, 2) listeye yeni parametre eklemeyi unutmamalısınız, 3) yeni parametrenin yerleştirilmesi gereken listede doğru noktayı seçmeye çalışın.
Ruslan

2
Sadece çalmak istiyorum ve C # 6'daki yaklaşan dize enterpolasyon özelliği hakkında bilgi verin. Aynı sonucu almak için "İfade: \ {a} + \ {b} = \ {sum}" yazacaksınız. codeproject.com/Articles/846566/…
cwap

-2

Eğer kullanırsanız +birleştirme, kendisini kullanan String.Concatyöntem. Dizenin kendisi bir + işleci göstermez.

Örneğin:

int i = 10;
string str = "hello" + i;

derlendi:

int i = 10;
object o1 = "hello";
object o2 = i; // Note boxing
string str = string.Concat(o1, o2);

Doğrudan ararsanız ToString, bokstan kaçınır ve Concat(string, string)aşırı yükü çağırır . Bu nedenle, ToStringyeterince önemli olmasa da çağrı biraz daha verimli olacaktır. Daha okunabilir olduğunu düşündüğünüz örneğe gitseniz iyi olur.


2
Bu sadece önceki cevapta yapılan ve açıklanan noktaları tekrarlıyor gibi görünüyor : "Dize birleştirme otomatik olarak dizeleri dizelere dönüştürür ..."
gnat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.