2015-12-19 14 views
17

Trong C#, chuỗi được thực tập. Tức là, nếu tôi tạo chuỗi foobar và sử dụng nó lần thứ hai, C# sẽ chỉ có một thể hiện của chuỗi trong bộ nhớ và mặc dù tôi sẽ có hai tham chiếu, cả hai đều sẽ trỏ đến cùng một cá thể chuỗi. Đây là một trong những lý do tại sao các chuỗi là và có được bất biến trong C#.Hai chuỗi giống hệt nhau có thể là hai cá thể riêng biệt trong C# không?

Bây giờ, câu hỏi của tôi là, có thể bằng cách nào đó tạo ra hai chuỗi giống nhau để chúng không bị tập trung, nhưng chúng ta kết thúc với hai thể hiện chuỗi khác nhau trong bộ nhớ, với hai địa chỉ khác nhau, cùng một văn bản?

Nếu có, làm cách nào?

Và, điều này có thể xảy ra vô tình hay bạn cần xây dựng kịch bản một cách rõ ràng cho trường hợp này?

Và cuối cùng: Giả sử có hai cá thể chuỗi riêng biệt trong bộ nhớ có cùng giá trị, chúng có bằng nhau (theo điều khoản của ==) không? Nếu vậy, làm cách nào để == hoạt động? Đầu tiên so sánh theo tham chiếu, sau đó theo giá trị, hoặc…?

+11

"Trong C#, chuỗi được thực tập nội trú. " Không họ không. Chuỗi * hằng số * được tập trung. Các cá thể chuỗi chỉ được tập trung nếu bạn gọi 'String.Intern'. Interning mỗi chuỗi trung gian sẽ rất lãng phí. –

+0

Được rồi, tôi không biết điều đó. Điều đó có nghĩa gì đối với hai trường hợp chuỗi có cùng giá trị? Họ có tham khảo cùng một "đối tượng" không? –

+0

@GoloRoden '==' trên chuỗi thực hiện so sánh chuỗi (thư-by-letter, nếu có) trong C#. Nó không quan trọng nếu chúng được interned hay không, và nó không quan trọng mà bộ nhớ mà họ đề cập đến. –

Trả lời

33

Trong C#, chuỗi được thực tập nội trú.

Không. Trong các chuỗi C# được phép thực tập. Đó là một tuyên bố rất khác.

Tức là, nếu tôi tạo chuỗi foobar và sử dụng nó lần thứ hai, C# sẽ chỉ có một thể hiện của chuỗi trong bộ nhớ và mặc dù tôi sẽ có hai tham chiếu, cả hai đều sẽ trỏ đến cùng một chuỗi dụ

số một lần nữa, trong C# runtime là phép để quyết định rằng một "foobar" cũng giống như nhau và thực tập họ, nhưng nó không phải là cần để làm như vậy.

Tất nhiên, nếu bạn sao chép tham chiếu thì tham chiếu sẽ được sao chép. Nhưng nếu bạn tạo ra một chuỗi thứ hai trông giống như một chuỗi trước đó, không có yêu cầu rằng nó được interned.

Trong thực tế, dây đang thực tập nội trú khi họ literals:

string x = "foobar"; 
string y = "foobar"; 
// x is reference equal to y 

hoặc khi họ có thể được tính là giống hệt nhau bởi trình biên dịch:

string x = "foobar"; 
string y = "foo" + "bar"; 
// x is reference equal to y 

Hoặc khi bạn nói một cách rõ ràng thời gian chạy mà bạn muốn thực tập một chuỗi cụ thể. Nếu chuỗi không thường thực tập nội trú:

string x = "foobar"; 
string y = "f" + x.Substring(1); 
// x and y are not reference equal 
+0

Ngoài ra, tôi muốn đề cập đến, rằng việc thực tập chỉ hoạt động trong phạm vi lắp ráp. Cố vấn có thể sửa tôi nếu tôi sai. –

+1

@HamletHakobyan: Tốt. Thông thường chuỗi ký tự được tự động tập trung khi chúng xảy ra hai lần trong cùng một assembly, nhưng không nhất thiết khi hai chữ cái xuất hiện trong hai assembly khác nhau. Một lần nữa thời gian chạy có thể chọn để làm như vậy, nhưng trong thực tế tôi không tin nó. –

10

Chỉ chuỗi ký tự chuỗi được thực tập. Thời gian chạy thực tập là tốn kém, do đó các chuỗi được tạo động không được thực hiện (trừ khi bạn thực tập rõ ràng bằng cách gọi String.Intern).

Các chuỗi sau tất cả những trường hợp khác nhau (bạn có thể kiểm tra nó bằng cách sử object.ReferenceEquals()):

string str1 = "foo"; 
string str2 = "FOO".ToLower(); 
string str3 = new StringBuilder().Append("f").Append("oo").ToString(); 

Nhà điều hành == bị quá tải cho string để so sánh chúng theo giá trị, chứ không phải bằng cách tham khảo

public static bool operator == (String a, String b) 
{ 
    return String.Equals(a, b); 
} 

Khi sử dụng toán tử ==, bạn phải nhớ rằng toán tử không đa hình. Vì vậy, nếu loại biên dịch của cả hai toán hạng là string, quá tải string sẽ được sử dụng. Nếu ít nhất một trong số họ là object, so sánh tham chiếu sẽ được thực hiện

string str1 = "foo"; 
string str2 = "FOO".ToLower(); 
object str3 = str2; 
bool valueComparison = str1 == str2;  // true - the same value 
bool referenceComparison = str1 == str3; // false - different instances 
+0

'str3' không phải là chuỗi trừ khi bạn thêm' .ToString() 'vào chuỗi. Ngoài ra, bạn có thể muốn thêm một cuộc biểu diễn 'Object.ReferenceEquals()' để hiển thị chúng là các đối tượng thật sự khác nhau. –

+0

@JeroenMostert Cảm ơn vì đã chú ý đến nó. –

4

Dưới đây là một thử nghiệm rất đơn giản chứng minh rằng 2 chuỗi tương đương không phải lúc nào trỏ đến tài liệu tham khảo cùng một đối tượng:

static void Main(string[] args) 
{ 
    string str1 = "foo"; 
    string str2 = "f"; 
    str2 += "oo"; 
    Console.WriteLine(str1 == str2); // prints true (value equality check) 
    Console.WriteLine(object.ReferenceEquals(str1, str2)); // prints false (reference equality check) 
} 
Các vấn đề liên quan