C # 'da değişebilen ve değişmeyen bir dize arasındaki fark nedir?
C # 'da değişebilen ve değişmeyen bir dize arasındaki fark nedir?
Yanıtlar:
Mutable ve immutable, "değişebilir" ve "değiştirilemez" anlamına gelen İngilizce kelimelerdir. Kelimelerin anlamı BT bağlamında aynıdır; yani
Bu kelimelerin anlamları diğer programlama dillerinde / ortamlarında olduğu gibi C # / .NET ile aynıdır, ancak türlerin isimleri diğer ayrıntılarda olduğu gibi farklılık gösterebilir.
Kayıt için:
String
standart C # / .Net değişmez dize türüdür StringBuilder
standart C # / .Net değiştirilebilir dize türüdür C # olarak temsil edilen bir dizede "bir değişiklik yapmak" için String
, aslında yeni bir String
nesne oluşturursunuz. Orijinal String
değiştirilmez ... çünkü değiştirilemez.
Çoğu durumda kullanmak daha iyidir, String
çünkü onlar hakkında daha kolay bir nedendir; örneğin, başka bir iş parçacığının "dizgimi değiştirebileceğini" düşünebilirsiniz. Ancak, bir işlem dizisi kullanarak bir dize oluşturmanız veya değiştirmeniz gerektiğinde, a kullanmak daha verimli olabilir StringBuilder
.
Ve son olarak, StringBuilder
a'nın değişmez olmadığı için bir dize olmadığını iddia eden insanlar için Microsoft belgeleri şöyle açıklanır StringBuilder
:
"Değişken bir karakter dizesini temsil eder . Bu sınıf devralınamaz."
String
değişmez
yani, dizeler değiştirilemez. Bir dizeyi değiştirdiğinizde (örneğin ekleyerek), aslında yeni bir dize oluşturursunuz.
Ama StringBuilder
değişmez değil (daha ziyade değişebilir)
Bu nedenle, bir dizeyi birden çok kez birleştirme gibi birçok kez değiştirmeniz gerekiyorsa kullanın StringBuilder
.
O(N^2)
Davranışa yol açar ...
Bir nesne, oluşturulduktan sonra, üzerinde çeşitli işlemler çağrılarak durumu değiştirilebiliyorsa değiştirilebilir, aksi takdirde değişmezdir.
C # (ve .NET) 'de bir dize System.String sınıfı tarafından temsil edilir. string
Anahtar kelime, bu sınıf için bir diğer adıdır.
System.string sınıfı değişmez, yani bir kez devlet değiştirilemez oluşturulan .
Tüm operasyonlar Yani böyle bir ipe gerçekleştirmek Substring
, Remove
, Replace
, birleştirme kullanarak '+' operatör vb yeni dize oluşturmak ve bunu dönecektir.
Gösteri için aşağıdaki programa bakınız -
string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);
Bu sırasıyla 'string' ve 'mystring' yazdıracaktır.
İçin değişmezlik yararları ve neden dize değişmez onay olan .NET dize değişmez Neden? .
Sık sık değiştirmek istediğiniz bir dizeye sahip olmak istiyorsanız StringBuilder
sınıfı kullanabilirsiniz . Bir StringBuilder
örnek üzerindeki işlemler aynı nesneyi değiştirir .
Daha fazla öneri için ne zaman kullanılacağını StringBuilder
ifade StringBuilder ne zaman kullanılır? .
Tüm string
nesneler C # ile değiştirilemez. Sınıfın nesneleri string
, bir kez yaratıldığında, inşa edildiklerinden başka hiçbir değeri temsil edemezler. Bir dizeyi "değiştiriyor" gibi görünen tüm işlemler bunun yerine yeni bir tane oluşturur. Bu bellekle verimsizdir, ancak bir dizenin sizin altında form değiştirmeyeceğine güvenebilme açısından son derece kullanışlıdır - çünkü referansınızı değiştirmediğiniz sürece, atıfta bulunulan dize asla değişmeyecektir.
Değişken bir nesnenin aksine, değiştirilebilecek veri alanları vardır. Bir veya daha fazla yöntemi nesnenin içeriğini değiştirir veya içine yazıldığında nesnenin değerini değiştirecek bir Özelliğe sahiptir.
Değişken bir nesneniz varsa - String'e en çok benzeyen şey StringBuffer
- o zaman altından değişmeyeceğinden emin olmak istiyorsanız bir kopyasını oluşturmanız gerekir. Değişken nesnelerin herhangi bir biçiminin Dictionary
veya kümesinin anahtarları olarak kullanılması tehlikelidir, bu nedenle nesnelerin kendileri değişebilir ve veri yapısının bilmenin hiçbir yolu olmaz ve sonuçta programınızı çökertir.
Bununla birlikte, içeriğini değiştirebilirsiniz - bu nedenle, tek bir karakteri veya benzer bir şeyi değiştirmek istediğiniz için tam bir kopya yapmaktan çok, çok daha fazla bellek verimlidir.
Genel olarak, doğru olan şey, bir şey oluştururken değiştirilebilir nesneleri ve işiniz bittiğinde değişmez nesneleri kullanmaktır. Bu elbette değişmez biçimlere sahip nesneler için geçerlidir; koleksiyonların çoğu değil. Bununla birlikte, koleksiyonunuzun dahili durumunu başka bağlamlara gönderirken değişmez olanın eşdeğeri olan salt okunur koleksiyon formları sağlamak genellikle yararlıdır, aksi takdirde bir şey bu dönüş değerini alabilir, bir şeyler yapabilir ve veri.
Değişmez:
Bir nesne üzerinde bazı işlemler yaptığınızda, yeni bir nesne oluşturur, bu nedenle durum dize durumunda olduğu gibi değiştirilemez.
değişken
Bir nesne üzerinde bazı işlemler gerçekleştirdiğinizde, nesnenin kendisi, StringBuilder durumunda olduğu gibi yeni bir obje oluşturulmadığını değiştirdi
.NET'te System.String (aka string) değişmez bir nesnedir. Bu, bir nesne oluşturduğunuzda daha sonra değerini değiştiremeyeceğiniz anlamına gelir. Yalnızca değişmez bir nesneyi yeniden oluşturabilirsiniz.
System.Text.StringBuilder, System.String öğesinin değiştirilebilir eşdeğeridir ve değerini değiştirebilirsiniz
Örneğin:
class Program
{
static void Main(string[] args)
{
System.String str = "inital value";
str = "\nsecond value";
str = "\nthird value";
StringBuilder sb = new StringBuilder();
sb.Append("initial value");
sb.AppendLine("second value");
sb.AppendLine("third value");
}
}
Aşağıdaki MSIL oluşturur: Kodu araştırırsanız. Bir System.String nesnesini değiştirdiğinizde aslında yeni bir nesne oluşturduğunuzu göreceksiniz. Ancak System.Text.StringBuilder'da metnin değerini her değiştirdiğinizde nesneyi yeniden oluşturmazsınız.
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 62 (0x3e)
.maxstack 2
.locals init ([0] string str,
[1] class [mscorlib]System.Text.StringBuilder sb)
IL_0000: nop
IL_0001: ldstr "inital value"
IL_0006: stloc.0
IL_0007: ldstr "\nsecond value"
IL_000c: stloc.0
IL_000d: ldstr "\nthird value"
IL_0012: stloc.0
IL_0013: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_0018: stloc.1
IL_0019: ldloc.1
IL_001a: ldstr "initial value"
IL_001f: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
IL_0024: pop
IL_0025: ldloc.1
IL_0026: ldstr "second value"
IL_002b: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
IL_0030: pop
IL_0031: ldloc.1
IL_0032: ldstr "third value"
IL_0037: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
IL_003c: pop
IL_003d: ret
} // end of method Program::Main
.NET sahne arkasında dize havuzu kullandığından dizeler değiştirilebilir. Anlamı :
string name = "My Country";
string name2 = "My Country";
Hem ad hem de ad2, dize havuzundaki aynı bellek konumuna başvuruyor. Şimdi name2'yi şu şekilde değiştirmek istediğinizi varsayalım:
name2 = "My Loving Country";
Dize havuzuna "Sevgi dolu ülkem" için dize havuzuna bakacak, eğer bulursanız, diğer akıllıca yeni dize "Sevgi dolu ülkem" dize havuzunda oluşturulacak ve name2 buna referans alacaktır. Ama bu " Sürecim " sürecinin tamamı değişmedi çünkü isim gibi diğer değişkenler hala kullanıyor. Dize bu yüzden DEMİR DEĞİLDİR .
StringBuilder farklı şekilde çalışır ve string havuzu kullanmaz. Herhangi bir StringBuilder örneği oluşturduğumuzda:
var address = new StringBuilder(500);
Bu örnek için 500 bayt boyutundaki bellek yığınını ayırır ve tüm işlemler bu bellek konumunu değiştirir ve bu bellek başka bir nesneyle paylaşılmaz. Ve bu nedeni budur StringBuilder olduğunu DEĞİŞKEN .
Umarım yardımcı olur.
Aslında yok. String sınıfı değiştirilebilir.
unsafe
{
string foo = string.Copy("I am immutable.");
fixed (char* pChar = foo)
{
char* pFoo = pChar;
pFoo[5] = ' ';
pFoo[6] = ' ';
}
Console.WriteLine(foo); // "I am mutable."
}
Bu tür bir mantık aslında String ve StringBuilder sınıflarında her zaman yapılır. Concat, Substring, vb. Teller kendilerini değiştirmezler, bu yüzden neden "değişmez" olarak kabul edilirler.
Bu arada, bunu dize değişmezleriyle denemeyin , aksi takdirde programınızı kötü bir şekilde karıştırırsınız:
string bar = "I am a string.";
fixed (char* pChar = bar)
{
char* pBar = pChar;
pBar[2] = ' ';
}
string baz = "I am a string.";
Console.WriteLine(baz); // "I m a string."
Bunun nedeni, dize değişmezlerinin masaüstü .NET Framework'te stajyer olması; başka bir deyişle, bar
ve baz
aynı dizeye noktaya, yani bir başka dönüşecek mutasyona. Bu, dize stajyerliği olmayan WinRT gibi yönetilmeyen bir platform kullanıyorsanız, hepsi iyi ve züppe.
Açıklığa kavuşturmak için C # (veya genel olarak .NET) değişken bir dize diye bir şey yoktur. Diğer diller değiştirilebilir değişken dizeleri (değişebilen dize) destekler ancak .NET çerçevesi desteklemez.
Yani sorunuzun doğru cevabı ALL dizesi C # ile değiştirilemez.
string'in belirli bir anlamı vardır. "string" lowercase anahtar sözcüğü, System.String sınıfından başlatılan bir nesne için yalnızca bir kısayoldur. String sınıfından oluşturulan tüm nesneler HER ZAMAN değiştirilemez.
Değişken bir metin temsili istiyorsanız StringBuilder gibi başka bir sınıf kullanmanız gerekir. StringBuilder, yinelenen bir şekilde 'kelimeler' koleksiyonu oluşturmanıza ve daha sonra bunu bir dizeye dönüştürmenize olanak tanır (bir kez daha değişmez).
StringBuilder
bununla çelişiyor: bkz. Msdn.microsoft.com/en-us/library/…
Veri değeri değiştirilemez. Not: Değişken değeri değiştirilebilir, ancak orijinal değiştirilemez veri değeri atıldı ve bellekte yeni bir veri değeri oluşturuldu.
itibaren http://yassershaikh.com/what-is-the-difference-between-strings-and-stringbuilder-in-c-net/
Kısa Cevap: String değişmezken, StringBuilder değiştirilebilir.
Bu ne anlama geliyor ? Wiki diyor ki: Nesneye yönelik olarak, değişmez bir nesne, durumu oluşturulduktan sonra değiştirilemeyen bir nesnedir. Bu, oluşturulduktan sonra değiştirilebilen değiştirilebilir bir nesnenin aksine.
StringBuilder Class belgelerinden:
String nesnesi değiştirilemez. System.String sınıfındaki yöntemlerden birini her kullandığınızda, bellekte yeni bir dize nesnesi oluşturursunuz; bu, yeni nesne için yeni bir alan ayırmayı gerektirir.
Bir dizede tekrarlanan değişiklikler yapmanız gereken durumlarda, yeni bir String nesnesi oluşturmayla ilişkili ek yük maliyetli olabilir.
System.Text.StringBuilder sınıfı, yeni bir nesne oluşturmadan bir dizeyi değiştirmek istediğinizde kullanılabilir. Örneğin, StringBuilder sınıfını kullanmak, bir dizede birçok dizeyi birleştirirken performansı artırabilir.
Immective string ve Mutable string builder örneği
Console.WriteLine("Mutable String Builder");
Console.WriteLine("....................................");
Console.WriteLine();
StringBuilder sb = new StringBuilder("Very Good Morning");
Console.WriteLine(sb.ToString());
sb.Remove(0, 5);
Console.WriteLine(sb.ToString());
Console.WriteLine();
Console.WriteLine("Immutable String");
Console.WriteLine("....................................");
Console.WriteLine();
string s = "Very Good Morning";
Console.WriteLine(s);
s.Substring(0, 5);
Console.WriteLine(s);
Console.ReadLine();
C # dizesi değişmez. Herhangi bir dize ile birleştirirseniz, aslında yeni bir dize yapıyorsunuz, bu yeni dize nesnesi! Ancak StringBuilder değiştirilebilir dize oluşturur.
StringBuilder çok büyük bir veri dizesini birleştirmek için daha iyi bir seçenektir çünkü StringBuilder değiştirilebilir bir dize türüdür ve StringBuilder nesnesi değişmez bir türdür, yani StringBuilder dizeyi bitirirken asla yeni bir nesne örneği oluşturmaz.
Birleştirme için ulaşmak için StringBuilder yerine string kullanırsak, her seferinde bellekte yeni bir örnek oluşturur.