Sự khác biệt giữa một chuỗi có thể thay đổi và bất biến trong C # là gì?
Sự khác biệt giữa một chuỗi có thể thay đổi và bất biến trong C # là gì?
Câu trả lời:
Có thể thay đổi và không thay đổi là các từ tiếng Anh có nghĩa là "có thể thay đổi" và "không thể thay đổi" tương ứng. Ý nghĩa của các từ là giống nhau trong bối cảnh CNTT; I E
Ý nghĩa của những từ này giống nhau trong C # / .NET như trong các ngôn ngữ / môi trường lập trình khác, mặc dù (rõ ràng) tên của các loại có thể khác nhau, cũng như các chi tiết khác.
Đối với hồ sơ:
String
là loại chuỗi bất biến C # / .Net tiêu chuẩn StringBuilder
là loại chuỗi có thể thay đổi C # / .Net tiêu chuẩn Để "thực hiện thay đổi" trên chuỗi được biểu thị dưới dạng C # String
, bạn thực sự tạo một String
đối tượng mới . Bản gốc String
không thay đổi ... bởi vì nó không thể thay đổi.
Trong hầu hết các trường hợp, tốt hơn là sử dụng String
vì đó là lý do dễ dàng hơn về chúng; ví dụ: bạn không cần xem xét khả năng một số luồng khác có thể "thay đổi chuỗi của tôi". Tuy nhiên, khi bạn cần xây dựng hoặc sửa đổi một chuỗi bằng cách sử dụng một chuỗi các hoạt động, có thể hiệu quả hơn để sử dụng một StringBuilder
.
Và cuối cùng, đối với những người khẳng định rằng a StringBuilder
không phải là một chuỗi bởi vì nó không phải là bất biến, tài liệu của Microsoft mô tả StringBuilder
như vậy:
"Đại diện cho một chuỗi các ký tự có thể thay đổi . Lớp này không thể được kế thừa."
String
là bất biến
tức là các chuỗi không thể được thay đổi. Khi bạn thay đổi một chuỗi (bằng cách thêm vào chuỗi chẳng hạn), bạn thực sự đang tạo một chuỗi mới.
Nhưng StringBuilder
không phải là bất biến (đúng hơn là nó có thể thay đổi)
Vì vậy, nếu bạn phải thay đổi một chuỗi nhiều lần, chẳng hạn như nhiều nối, sau đó sử dụng StringBuilder
.
O(N^2)
hành vi ...
Một đối tượng có thể thay đổi nếu, một khi được tạo, trạng thái của nó có thể được thay đổi bằng cách gọi các hoạt động khác nhau trên nó, nếu không nó là bất biến.
Trong C # (và .NET), một chuỗi được đại diện bởi lớp System.String. Các string
từ khóa là một bí danh cho các lớp học này.
Lớp System.String là bất biến, tức là một khi được tạo, trạng thái của nó không thể thay đổi .
Vì vậy, tất cả các hoạt động bạn thực hiện trên một chuỗi như Substring
, Remove
, Replace
, nối sử dụng '+' điều hành vv sẽ tạo ra một chuỗi mới và gửi lại.
Xem chương trình sau đây để trình diễn -
string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);
Điều này sẽ in 'chuỗi' và 'bí ẩn' tương ứng.
Vì lợi ích của tính bất biến và tại sao chuỗi là bất biến kiểm tra Tại sao .NET String là bất biến? .
Nếu bạn muốn có một chuỗi mà bạn muốn sửa đổi thường xuyên, bạn có thể sử dụng StringBuilder
lớp. Các hoạt động trên một StringBuilder
thể hiện sẽ sửa đổi cùng một đối tượng .
Để được tư vấn thêm về thời điểm sử dụng, StringBuilder
hãy tham khảo Khi nào nên sử dụng StringBuilder? .
Tất cả string
các đối tượng là bất biến trong C #. Các đối tượng của lớp string
, một khi được tạo, không bao giờ có thể biểu thị bất kỳ giá trị nào ngoài giá trị mà chúng được tạo. Tất cả các hoạt động dường như "thay đổi" một chuỗi thay vì tạo ra một chuỗi mới. Điều này không hiệu quả với bộ nhớ, nhưng cực kỳ hữu ích liên quan đến việc có thể tin tưởng rằng một chuỗi sẽ không thay đổi hình thức theo bạn - vì miễn là bạn không thay đổi tham chiếu của mình, chuỗi được nhắc đến sẽ không bao giờ thay đổi.
Một đối tượng có thể thay đổi, ngược lại, có các trường dữ liệu có thể được thay đổi. Một hoặc nhiều phương thức của nó sẽ thay đổi nội dung của đối tượng hoặc nó có Thuộc tính mà khi được viết vào sẽ thay đổi giá trị của đối tượng.
Nếu bạn có một đối tượng có thể thay đổi - đối tượng tương tự nhất với Chuỗi là StringBuffer
- thì bạn phải tạo một bản sao của nó nếu bạn muốn chắc chắn rằng nó sẽ không thay đổi từ bên dưới bạn. Đây là lý do tại sao các đối tượng có thể thay đổi rất nguy hiểm khi sử dụng làm khóa thành bất kỳ hình thức Dictionary
hoặc tập hợp nào - chính các đối tượng có thể thay đổi và cấu trúc dữ liệu sẽ không có cách nào để biết, dẫn đến dữ liệu bị hỏng, cuối cùng sẽ làm hỏng chương trình của bạn.
Tuy nhiên, bạn có thể thay đổi nội dung của nó - vì vậy, nó hiệu quả hơn nhiều về bộ nhớ so với việc tạo một bản sao hoàn chỉnh vì bạn muốn thay đổi một ký tự hoặc một cái gì đó tương tự.
Nói chung, điều đúng đắn cần làm là sử dụng các đối tượng có thể thay đổi trong khi bạn đang tạo một cái gì đó và các đối tượng bất biến sau khi bạn hoàn thành. Điều này áp dụng cho các đối tượng có hình thức bất biến, tất nhiên; hầu hết các bộ sưu tập không. Tuy nhiên, việc cung cấp các hình thức bộ sưu tập chỉ đọc là tương đối hữu ích, tương đương với bất biến, khi gửi trạng thái bên trong của bộ sưu tập của bạn đến các bối cảnh khác - nếu không, một cái gì đó có thể lấy giá trị trả về đó, làm gì đó cho nó và làm hỏng dữ liệu.
Bất biến:
Khi bạn thực hiện một số thao tác trên một đối tượng, nó sẽ tạo ra một đối tượng mới do đó trạng thái không thể sửa đổi như trong trường hợp chuỗi.
Có thể thay đổi
Khi bạn thực hiện một số thao tác trên một đối tượng, chính đối tượng đã sửa đổi không có vật cản mới nào được tạo như trong trường hợp của StringBuilder
Trong .NET System.String (còn gọi là chuỗi) là một đối tượng bất biến. Điều đó có nghĩa là khi bạn tạo một đối tượng, bạn không thể thay đổi giá trị của nó sau đó. Bạn chỉ có thể tạo lại một đối tượng bất biến.
System.Text.StringBuilder tương đương với System.String và bạn có thể kiểm tra giá trị của nó
Ví dụ:
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");
}
}
Tạo MSIL sau: Nếu bạn điều tra mã. Bạn sẽ thấy rằng bất cứ khi nào bạn chọn một đối tượng của System.String bạn thực sự đang tạo một đối tượng mới. Nhưng trong System.Text.StringBuilder bất cứ khi nào bạn thay đổi giá trị của văn bản, bạn không tạo lại đối tượng.
.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
Các chuỗi có thể thay đổi vì .NET sử dụng chuỗi chuỗi phía sau cảnh. Nó có nghĩa là:
string name = "My Country";
string name2 = "My Country";
Cả name và name2 đều đề cập đến cùng một vị trí bộ nhớ từ nhóm chuỗi. Bây giờ giả sử bạn muốn thay đổi name2 thành:
name2 = "My Loving Country";
Nó sẽ xem xét nhóm chuỗi cho chuỗi "Quốc gia yêu thương của tôi", nếu tìm thấy bạn sẽ nhận được tham chiếu của chuỗi mới thông minh khác "Quốc gia yêu thương của tôi" sẽ được tạo trong nhóm chuỗi và name2 sẽ nhận được tham chiếu về chuỗi đó. Nhưng toàn bộ quá trình " Quốc gia của tôi " không thay đổi vì tên khác như tên vẫn đang sử dụng. Và đó là lý do tại sao chuỗi là NGAY LẬP TỨC .
StringBuilder hoạt động theo cách khác nhau và không sử dụng chuỗi chuỗi. Khi chúng tôi tạo bất kỳ phiên bản nào của StringBuilder:
var address = new StringBuilder(500);
Nó phân bổ đoạn bộ nhớ có kích thước 500 byte cho trường hợp này và tất cả các hoạt động chỉ sửa đổi vị trí bộ nhớ này và bộ nhớ này không được chia sẻ với bất kỳ đối tượng nào khác. Và đó là lý do tại sao StringBuilder là MUTABLE .
Tôi mong nó sẽ có ích.
Không, thực sự. Lớp String có thể thay đổi.
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."
}
Kiểu logic này được thực hiện mọi lúc trong các lớp String và StringBuilder. Họ chỉ phân bổ một chuỗi mới mỗi khi bạn gọi Concat, Sub chuỗi, v.v. và sử dụng số học con trỏ để sao chép sang chuỗi mới. Các chuỗi không tự biến đổi, do đó tại sao chúng được coi là "bất biến".
Bằng cách này, đừng không cố gắng này với xâu hoặc bạn sẽ tồi tệ lộn xộn lên chương trình của bạn:
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."
Điều này là do chuỗi ký tự được đặt trong .NET Framework của máy tính để bàn; nói cách khác, bar
và baz
trỏ đến cùng một chuỗi, do đó, một chuỗi sẽ biến đổi chuỗi khác. Đây là tất cả tốt đẹp và mặc dù nếu bạn đang sử dụng một nền tảng không được quản lý như WinRT, mà thiếu thực tập chuỗi.
Để làm rõ, không có thứ gọi là chuỗi có thể thay đổi trong C # (hay .NET nói chung). Các langu khác hỗ trợ các chuỗi có thể thay đổi (chuỗi có thể thay đổi) nhưng .NET framework thì không.
Vì vậy, câu trả lời chính xác cho câu hỏi của bạn là TẤT CẢ chuỗi là bất biến trong C #.
chuỗi có một ý nghĩa cụ thể. Từ khóa chữ thường "chuỗi" chỉ là một lối tắt cho một đối tượng được khởi tạo từ lớp System.String. Tất cả các đối tượng được tạo từ lớp chuỗi là LUÔN LUÔN.
Nếu bạn muốn một đại diện văn bản có thể thay đổi thì bạn cần sử dụng một lớp khác như StringBuilder. StringBuilder cho phép bạn lặp đi lặp lại một bộ sưu tập 'từ' và sau đó chuyển đổi nó thành một chuỗi (một lần nữa không thay đổi).
StringBuilder
mâu thuẫn với điều này: xem msdn.microsoft.com/en-us/l Library / từ
Giá trị dữ liệu có thể không được thay đổi. Lưu ý: Giá trị biến có thể được thay đổi, nhưng giá trị dữ liệu bất biến ban đầu đã bị loại bỏ và giá trị dữ liệu mới được tạo trong bộ nhớ.
Từ http://yassershaikh.com/what-is-the-difference-b between-strings-and-Stringbuilder-in-c-net /
Câu trả lời ngắn: Chuỗi là bất biến - trong khi StringBuilder có thể thay đổi.
Điều đó nghĩa là gì ? Wiki cho biết: Trong hướng đối tượng, một đối tượng bất biến là một đối tượng có trạng thái không thể sửa đổi sau khi được tạo. Điều này trái ngược với một đối tượng có thể thay đổi, có thể được sửa đổi sau khi nó được tạo.
Từ tài liệu Lớp StringBuilder:
Đối tượng String là bất biến. Mỗi khi bạn sử dụng một trong các phương thức trong lớp System.String, bạn sẽ tạo một đối tượng chuỗi mới trong bộ nhớ, yêu cầu phân bổ không gian mới cho đối tượng mới đó.
Trong các tình huống mà bạn cần thực hiện sửa đổi lặp đi lặp lại thành một chuỗi, chi phí liên quan đến việc tạo một đối tượng Chuỗi mới có thể tốn kém.
Lớp System.Text.StringBuilder có thể được sử dụng khi bạn muốn sửa đổi một chuỗi mà không tạo một đối tượng mới. Ví dụ, sử dụng lớp StringBuilder có thể tăng hiệu suất khi nối nhiều chuỗi với nhau trong một vòng lặp.
Dưới đây là ví dụ cho trình tạo chuỗi bất biến và trình tạo chuỗi Mutable
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();
Chuỗi trong C # là bất biến. Nếu bạn nối nó với bất kỳ chuỗi nào, bạn thực sự đang tạo một chuỗi mới, đó là đối tượng chuỗi mới! Nhưng StringBuilder tạo ra chuỗi có thể thay đổi.
StringBuilder là một tùy chọn tốt hơn để nối chuỗi dữ liệu khổng lồ vì StringBuilder là loại chuỗi có thể thay đổi và đối tượng StringBuilder là loại không thay đổi, điều đó có nghĩa là StringBuilder không bao giờ tạo đối tượng mới trong khi nối chuỗi.
Nếu chúng ta đang sử dụng chuỗi thay vì StringBuilder để đạt được kết nối thì nó sẽ tạo ra thể hiện mới trong bộ nhớ mỗi lần.