ความแตกต่างระหว่างสตริงที่ไม่แน่นอนและไม่เปลี่ยนรูปใน C # คืออะไร?
ความแตกต่างระหว่างสตริงที่ไม่แน่นอนและไม่เปลี่ยนรูปใน C # คืออะไร?
คำตอบ:
ไม่แน่นอนและไม่เปลี่ยนรูปเป็นคำภาษาอังกฤษหมายถึง "สามารถเปลี่ยน" และ "ไม่สามารถเปลี่ยน" ตามลำดับ ความหมายของคำนั้นเหมือนกันในบริบทไอที กล่าวคือ
ความหมายของคำเหล่านี้จะเหมือนกันใน C # / .NET เหมือนกับในภาษาโปรแกรม / สภาพแวดล้อมอื่น ๆ แม้ว่าชื่อประเภทนั้นอาจแตกต่างกันออกไป (อย่างชัดเจน) เช่นเดียวกับรายละเอียดอื่น ๆ
สำหรับบันทึก:
String
คือสตริงสตริงที่ไม่เปลี่ยนรูปแบบมาตรฐาน C # / .Net StringBuilder
เป็นชนิดสตริงที่ผันแปรได้ของ C # / .Net มาตรฐาน ในการ "ทำให้เกิดการเปลี่ยนแปลง" บนสตริงที่แสดงเป็น C # String
คุณจะต้องสร้างString
วัตถุใหม่ ต้นฉบับString
ไม่เปลี่ยนแปลง ... เนื่องจากไม่สามารถเปลี่ยนได้
ในกรณีส่วนใหญ่จะดีกว่าที่จะใช้String
เพราะมันเป็นเหตุผลที่ง่ายกว่าเกี่ยวกับพวกเขา; เช่นคุณไม่จำเป็นต้องพิจารณาความเป็นไปได้ที่เธรดอื่น ๆ อาจ "เปลี่ยนสตริงของฉัน" StringBuilder
แต่เมื่อคุณต้องสร้างหรือปรับเปลี่ยนสตริงโดยใช้ลำดับของการดำเนินงานก็อาจจะมีประสิทธิภาพมากขึ้นในการใช้
และในที่สุดสำหรับคนเหล่านั้นที่ยืนยันว่า a StringBuilder
ไม่ใช่สตริงเพราะมันไม่เปลี่ยนรูปเอกสารของ Microsoft อธิบายStringBuilder
ดังนี้:
"แสดงสตริงของอักขระที่ไม่แน่นอนได้คลาสนี้ไม่สามารถสืบทอดได้"
String
ไม่เปลี่ยนรูป
เช่นสตริงไม่สามารถแก้ไขได้ เมื่อคุณเปลี่ยนสตริง (โดยการเพิ่มเข้าไป) คุณกำลังสร้างสตริงใหม่
แต่StringBuilder
ไม่เปลี่ยนแปลงไม่ได้ (ค่อนข้างจะไม่แน่นอน)
ดังนั้นถ้าคุณมีการปรับเปลี่ยนสตริงหลายครั้งเช่น concatenations StringBuilder
ต่างๆจากนั้นใช้
O(N^2)
พฤติกรรม ...
วัตถุไม่แน่นอนถ้าสร้างขึ้นเมื่อสถานะของมันสามารถเปลี่ยนแปลงได้โดยการเรียกการดำเนินงานต่างๆเกี่ยวกับมันมิฉะนั้นมันจะไม่เปลี่ยนรูป
ใน C # (และ. NET) สตริงจะถูกแทนด้วยคลาส System.String string
คำหลักคือนามแฝงสำหรับคลาสนี้
ระดับ System.String จะไม่เปลี่ยนรูปคือเมื่อสร้างแล้วรัฐไม่สามารถเปลี่ยนแปลง
ดังนั้นการดำเนินการทั้งหมดที่คุณดำเนินการในสตริงเหมือนSubstring
, Remove
, Replace
, เรียงต่อกันโดยใช้ '+' ผู้ประกอบการ ฯลฯ จะสร้างสตริงใหม่และส่งกลับมา
ดูโปรแกรมต่อไปนี้สำหรับการสาธิต -
string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);
สิ่งนี้จะพิมพ์ 'string' และ 'mystring' ตามลำดับ
เพื่อประโยชน์ของการเปลี่ยนแปลงไม่ได้และทำไมสตริงจึงไม่เปลี่ยนรูปเช็คทำไม. NET String ถึงไม่เปลี่ยนรูป? .
หากคุณต้องการมีสตริงที่คุณต้องการแก้ไขบ่อยครั้งคุณสามารถใช้StringBuilder
คลาส การดำเนินงานใน อินสแตนซ์จะปรับเปลี่ยนวัตถุเดียวกันStringBuilder
สำหรับคำแนะนำเพิ่มเติมเกี่ยวกับการใช้ StringBuilder
อ้างอิงถึงเมื่อใดควรใช้ StringBuilder .
string
วัตถุทั้งหมดไม่เปลี่ยนรูปใน C # วัตถุของชั้นเรียนที่string
สร้างขึ้นครั้งเดียวไม่สามารถเป็นตัวแทนของค่าใด ๆ นอกเหนือจากที่พวกเขาถูกสร้างขึ้นด้วย การดำเนินการทั้งหมดที่ดูเหมือนจะ "เปลี่ยน" สตริงแทนที่จะสร้างใหม่ สิ่งนี้ไม่มีประสิทธิภาพในหน่วยความจำ แต่มีประโยชน์อย่างยิ่งสำหรับการที่สามารถเชื่อถือได้ว่าสตริงจะไม่เปลี่ยนรูปแบบภายใต้คุณ - เพราะตราบใดที่คุณไม่เปลี่ยนการอ้างอิงสตริงที่ถูกอ้างถึงจะไม่เปลี่ยนแปลง
ตรงกันข้ามวัตถุที่เปลี่ยนแปลงไม่ได้มีเขตข้อมูลที่สามารถเปลี่ยนแปลงได้ วิธีการอย่างน้อยหนึ่งอย่างจะเปลี่ยนเนื้อหาของวัตถุหรือมีคุณสมบัติที่เมื่อถูกเขียนเข้าไปจะเปลี่ยนค่าของวัตถุ
หากคุณมีวัตถุที่ไม่แน่นอน - สิ่งที่คล้ายกับ String มากที่สุดคือStringBuffer
- คุณต้องทำสำเนาของมันหากคุณต้องการให้แน่ใจว่ามันจะไม่เปลี่ยนแปลงจากคุณ นี่คือเหตุผลที่วัตถุที่เปลี่ยนแปลงไม่ได้มีอันตรายที่จะใช้เป็นกุญแจในรูปแบบใด ๆDictionary
หรือตั้งค่าที่ตัวเองสามารถเปลี่ยนแปลงได้และโครงสร้างข้อมูลจะไม่มีทางรู้ซึ่งนำไปสู่ข้อมูลที่เสียหายซึ่งในที่สุดโปรแกรมของคุณก็จะพัง
อย่างไรก็ตามคุณสามารถเปลี่ยนเนื้อหาได้ดังนั้นจึงมีประสิทธิภาพมากขึ้นกว่าการทำสำเนาเพราะคุณต้องการเปลี่ยนอักขระเดียวหรืออะไรที่คล้ายกัน
โดยทั่วไปสิ่งที่ต้องทำคือใช้วัตถุที่ไม่แน่นอนในขณะที่คุณกำลังสร้างบางสิ่งและวัตถุที่ไม่เปลี่ยนรูปเมื่อคุณทำเสร็จแล้ว สิ่งนี้ใช้กับวัตถุที่มีรูปแบบที่เปลี่ยนแปลงไม่ได้แน่นอน คอลเลกชันส่วนใหญ่ไม่ได้ บ่อยครั้งที่มีประโยชน์ในการจัดหาคอลเลกชันรูปแบบอ่านอย่างเดียวซึ่งเทียบเท่ากับที่ไม่เปลี่ยนรูปเมื่อส่งสถานะภายในของคอลเลกชันของคุณไปยังบริบทอื่น - มิฉะนั้นบางสิ่งบางอย่างอาจใช้ค่าตอบแทนคืนนั้นทำบางสิ่ง ข้อมูล.
ไม่เปลี่ยนรูป:
เมื่อคุณทำการดำเนินการบางอย่างกับวัตถุมันจะสร้างวัตถุใหม่ดังนั้นรัฐจะไม่สามารถแก้ไขได้เช่นในกรณีของสตริง
ไม่แน่นอน
เมื่อคุณทำการดำเนินการบางอย่างบนวัตถุวัตถุเองปรับเปลี่ยนไม่สร้าง obect ใหม่เช่นเดียวกับในกรณีของ StringBuilder
ใน. NET System.String (สตริง aka) เป็นวัตถุที่ไม่เปลี่ยนรูป ซึ่งหมายความว่าเมื่อคุณสร้างวัตถุคุณจะไม่สามารถเปลี่ยนเป็นค่าได้ในภายหลัง คุณสามารถสร้างวัตถุที่ไม่เปลี่ยนรูปแบบได้เท่านั้น
System.Text.StringBuilder เทียบเท่ากับ System.String ที่ไม่แน่นอนและคุณสามารถเปลี่ยนค่าของมัน
ตัวอย่างเช่น:
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");
}
}
สร้าง MSIL ต่อไปนี้: หากคุณตรวจสอบรหัส คุณจะเห็นว่าเมื่อใดก็ตามที่คุณ chane วัตถุของ System.String คุณกำลังสร้างใหม่จริง ๆ แต่ใน System.Text.StringBuilder เมื่อใดก็ตามที่คุณเปลี่ยนค่าของข้อความคุณไม่ต้องสร้างวัตถุใหม่
.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 ใช้สตริงพูลเบื้องหลัง มันหมายถึง:
string name = "My Country";
string name2 = "My Country";
ทั้งชื่อและ name2 อ้างถึงตำแหน่งหน่วยความจำเดียวกันจากสตริงพูล ตอนนี้สมมติว่าคุณต้องการเปลี่ยน name2 เป็น:
name2 = "My Loving Country";
มันจะดูในสตริงพูลสำหรับสตริง "My Loving Country" หากพบว่าคุณจะได้รับการอ้างอิงสตริงใหม่อื่น ๆ ที่ชาญฉลาด "My Loving Country" จะถูกสร้างขึ้นในสตริงพูลและ name2 จะได้รับการอ้างอิงจากมัน แต่กระบวนการทั้งหมดนี้ " ประเทศของฉัน " ไม่ได้เปลี่ยนเพราะตัวแปรอื่น ๆ เช่นชื่อยังคงใช้อยู่ และนั่นคือเหตุผลที่ว่าทำไมสตริงมีไม่เปลี่ยนรูป
StringBuilderทำงานในลักษณะที่แตกต่างกันและไม่ใช้กลุ่มสตริง เมื่อเราสร้างตัวอย่างของ StringBuilder:
var address = new StringBuilder(500);
มันจัดสรรหน่วยความจำอันขนาด 500 ไบต์สำหรับอินสแตนซ์นี้และการดำเนินการทั้งหมดเพียงแค่แก้ไขตำแหน่งหน่วยความจำนี้และหน่วยความจำนี้ไม่ได้ใช้ร่วมกับวัตถุอื่น ๆ และนั่นคือเหตุผลที่ว่าทำไมStringBuilderคือไม่แน่นอน
ฉันหวังว่ามันจะช่วย
ไม่มีจริง คลาส String ไม่สามารถเปลี่ยนแปลงได้
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."
}
ตรรกะชนิดนี้ทำตลอดเวลาในคลาส String และ StringBuilder พวกเขาเพียงจัดสรรสตริงใหม่ทุกครั้งที่คุณเรียก Concat, Substring และอื่น ๆ และใช้เลขคณิตตัวชี้เพื่อคัดลอกไปยังสตริงใหม่ เงื่อนไขก็ไม่ได้กลายพันธุ์ตัวเองดังนั้นทำไมพวกเขาจึงถือว่า "ไม่เปลี่ยนรูป"
โดยวิธีการที่ไม่ได้พยายามนี้กับตัวอักษรของสตริงหรือคุณจะไม่ดีเลอะโปรแกรมของคุณ:
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."
นี่คือเนื่องจากตัวอักษรของสตริงจะ interned ในเดสก์ท็อป. NET Framework กล่าวอีกนัยหนึ่งbar
และbaz
ชี้ไปที่สตริงเดียวกันที่แน่นอนดังนั้นการกลายพันธุ์หนึ่งจะกลายพันธุ์อื่น ๆ ทั้งหมดนี้เป็นสิ่งที่ดีและสวยงามแม้ว่าคุณจะใช้แพลตฟอร์มที่ไม่มีการจัดการเช่น WinRT ซึ่งขาดสตริงการฝึกงาน
เพื่อชี้แจงไม่มีสิ่งเช่นสตริงที่ไม่แน่นอนใน C # (หรือ. NET โดยทั่วไป) langues อื่น ๆ สนับสนุนสตริงที่ไม่แน่นอน (สตริงซึ่งสามารถเปลี่ยนแปลงได้) แต่. NET Framework ไม่ได้
ดังนั้นคำตอบที่ถูกต้องสำหรับคำถามของคุณคือสตริงทั้งหมดไม่เปลี่ยนรูปใน C #
สตริงมีความหมายเฉพาะ คีย์เวิร์ด "string" ตัวพิมพ์เล็กเป็นเพียงทางลัดสำหรับวัตถุที่สร้างอินสแตนซ์จากคลาส System.String วัตถุทั้งหมดที่สร้างจากคลาสสตริงจะไม่เปลี่ยนรูปเสมอ
ถ้าคุณต้องการการแสดงข้อความที่ไม่แน่นอนคุณต้องใช้คลาสอื่นเช่น StringBuilder StringBuilder ช่วยให้คุณสามารถสร้างคอลเลกชันของ 'words' ซ้ำแล้วแปลงเป็นสตริง (เปลี่ยนรูปอีกครั้ง)
StringBuilder
ข้อขัดแย้งนี้: ดูmsdn.microsoft.com/en-us/library/ …
ค่าข้อมูลอาจไม่สามารถเปลี่ยนแปลงได้ หมายเหตุ: ค่าตัวแปรอาจเปลี่ยนแปลงได้ แต่ค่าข้อมูลที่ไม่เปลี่ยนรูปแบบเดิมนั้นถูกทิ้งไปและค่าข้อมูลใหม่จะถูกสร้างขึ้นในหน่วยความจำ
ในรายละเอียดการใช้งาน
System.String ของ CLR2 นั้นไม่แน่นอน StringBuilder.Append โทร String.AppendInplace (วิธีส่วนตัว)
System.String ของ CLR4 นั้นไม่เปลี่ยนรูป StringBuilder มีอาร์เรย์ Char พร้อมกับ chunking
จากhttp://yassershaikh.com/what-is-the-difference-between-strings-and-stringbuilder-in-c-net/
คำตอบสั้น ๆ : สตริงไม่เปลี่ยนรูป - ในขณะที่ StringBuilder ไม่แน่นอน
นั่นหมายความว่าอย่างไร ? Wiki พูดว่า: ในเชิงวัตถุวัตถุที่ไม่เปลี่ยนรูปนั้นเป็นวัตถุที่ไม่สามารถแก้ไขสถานะได้หลังจากสร้างขึ้นแล้ว นี่คือตรงกันข้ามกับวัตถุที่ไม่แน่นอนซึ่งสามารถแก้ไขได้หลังจากที่มันถูกสร้างขึ้น
จากเอกสาร StringBuilder Class:
วัตถุ String ไม่เปลี่ยนรูป ทุกครั้งที่คุณใช้วิธีใดวิธีหนึ่งในคลาส System.String คุณสร้างวัตถุสตริงใหม่ในหน่วยความจำซึ่งต้องการการจัดสรรพื้นที่ใหม่สำหรับวัตถุใหม่นั้น
ในสถานการณ์ที่คุณต้องทำการแก้ไขสตริงซ้ำ ๆ ค่าใช้จ่ายที่เกี่ยวข้องกับการสร้างวัตถุ String ใหม่อาจมีค่าใช้จ่ายสูง
คลาส System.Text.StringBuilder สามารถใช้เมื่อคุณต้องการแก้ไขสตริงโดยไม่ต้องสร้างวัตถุใหม่ ตัวอย่างเช่นการใช้คลาส StringBuilder สามารถเพิ่มประสิทธิภาพเมื่อเชื่อมสตริงจำนวนมากเข้าด้วยกันในลูป
นี่คือตัวอย่างสำหรับสตริงที่ไม่เปลี่ยนรูปและตัวสร้างสตริงที่ไม่แน่นอน
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 # ไม่เปลี่ยนรูป หากคุณต่อสตริงเข้ากับสตริงใด ๆ แสดงว่าคุณกำลังสร้างสตริงใหม่นั่นคือวัตถุสตริงใหม่! แต่ StringBuilder สร้างสตริงที่ไม่แน่นอน
StringBuilder เป็นตัวเลือกที่ดีกว่าในการเชื่อมสตริงข้อมูลขนาดใหญ่เนื่องจาก StringBuilder เป็นประเภทสตริงที่ไม่แน่นอนและวัตถุ StringBuilder เป็นประเภทที่ไม่เปลี่ยนรูปซึ่งหมายความว่า StringBuilder จะไม่สร้างอินสแตนซ์ใหม่ของวัตถุในขณะที่เชื่อมสตริง
ถ้าเราใช้ string แทน StringBuilder เพื่อให้ได้ concatenation มันจะสร้าง instance ใหม่ในหน่วยความจำทุกครั้ง