Xét đoạn mã sau:Chuỗi .NET có thực sự được coi là không thay đổi?
unsafe
{
string foo = string.Copy("This can't change");
fixed (char* ptr = foo)
{
char* pFoo = ptr;
pFoo[8] = pFoo[9] = ' ';
}
Console.WriteLine(foo); // "This can change"
}
này tạo ra một con trỏ tới ký tự đầu tiên của foo
, reassigns nó trở thành có thể thay đổi, và thay đổi các ký tự 8 và 9 vị trí lên đến ' '
.
Thông báo Tôi chưa bao giờ thực sự được giao lại foo
; thay vào đó, tôi đã thay đổi giá trị của nó bằng cách sửa đổi trạng thái của nó hoặc biến đổi chuỗi. Do đó, các chuỗi .NET có thể thay đổi được.
này hoạt động rất tốt, trên thực tế, đó là đoạn mã sau:
unsafe
{
string bar = "Watch this";
fixed (char* p = bar)
{
char* pBar = p;
pBar[0] = 'C';
}
string baz = "Watch this";
Console.WriteLine(baz); // Unrelated, right?
}
sẽ in "Catch this"
do chuỗi interning chữ.
này có rất nhiều công dụng được áp dụng, ví dụ này:
string GetForInputData(byte[] inputData)
{
// allocate a mutable buffer...
char[] buffer = new char[inputData.Length];
// fill the buffer with input data
// ...and a string to return
return new string(buffer);
}
được thay thế bằng:
string GetForInputData(byte[] inputData)
{
// allocate a string to return
string result = new string('\0', inputData.Length);
fixed (char* ptr = result)
{
// fill the result with input data
}
return result; // return it
}
Điều này có thể tiết kiệm chi phí phân bổ bộ nhớ/hiệu suất có khả năng rất lớn nếu bạn làm việc trong một speed- trường quan trọng (ví dụ như mã hóa). Tôi đoán bạn có thể nói rằng điều này không được tính vì nó "sử dụng hack" để làm cho con trỏ có thể thay đổi, nhưng sau đó lại là các nhà thiết kế ngôn ngữ C# đã hỗ trợ gán chuỗi cho con trỏ ở vị trí đầu tiên. (Trong thực tế, điều này được thực hiện allthetime nội bộ trong String
và StringBuilder
, vì vậy về mặt kỹ thuật bạn có thể làm StringBuilder của riêng bạn với điều này.)
Vì vậy, nên NET chuỗi thực sự được coi là bất biến?
Chúng không thay đổi khi sử dụng API công khai. Nếu bạn sử dụng mã không an toàn hoặc phản chiếu để bỏ qua API công khai đó thì không. – MarcinJuraszek
@MarcinJuraszek Con trỏ * là * một phần của API công khai, cũng xem đoạn cuối của tôi. –
Tôi đang nói về API công khai của lớp 'string' - các phương thức, thuộc tính mà nó hiển thị. – MarcinJuraszek