Theo thứ tự mã của bạn truy cập ...
==
bị ghi đè. Điều này có nghĩa là thay vì "abc" == "ab" + "c"
, hãy gọi số ==
mặc định cho các loại tham chiếu (so sánh tham chiếu chứ không phải giá trị) mà nó gọi vào string.Equals(a, b)
.
Bây giờ, điều này như sau:
- Nếu hai thực sự là tài liệu tham khảo cùng, trở thành sự thật.
- Nếu một trong hai là null, trả về false (chúng tôi đã trả về true ở trên nếu cả hai đều là null).
- nếu hai chiều dài khác nhau, trả về false;
- Thực hiện chu trình tối ưu hóa thông qua một chuỗi, so sánh nó với char còn lại với phần còn lại (int-for-int được xem như hai khối int trong bộ nhớ, là một trong những tối ưu liên quan). Nếu nó đạt đến kết thúc mà không có sự không khớp, sau đó trả về true, ngược lại trả về false.
Nói cách khác, nó bắt đầu với cái gì đó như:
public static bool ==(string x, string y)
{
//step 1:
if(ReferenceEquals(x, y))
return true;
//step 2:
if(ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
//step 3;
int len = x.Length;
if(len != y.Length)
return false;
//step 4:
for(int i = 0; i != len; ++i)
if(x[i] != y[i])
return false;
return true;
}
Trừ bước 4 là một phiên bản dựa trên con trỏ với một vòng lặp unrolled rằng nên vì thế lý tưởng được nhanh hơn. Tôi sẽ không thể hiện điều đó bởi vì tôi muốn nói về logic tổng thể.
Có các vết cắt ngắn đáng kể. Đầu tiên là ở bước 1. Vì sự bình đẳng là phản xạ (danh tính đòi hỏi sự bình đẳng, a == a
) thì chúng ta có thể trả về true trong nano giây cho dù chỉ một vài chuỗi MB, nếu so sánh với chính nó.
Bước 2 không phải là cắt ngắn, vì điều kiện phải được kiểm tra, nhưng lưu ý rằng vì chúng tôi đã trả lại giá trị đúng cho (string)null == (string)null
, chúng tôi không cần một chi nhánh khác. Vì vậy, thứ tự của cuộc gọi được hướng đến một kết quả nhanh chóng.
Bước 3 cho phép hai điều. Cả hai đều cắt ngắn trên các chuỗi có độ dài khác nhau (luôn luôn sai) và có nghĩa là người ta không thể vô tình bắn qua cuối của một chuỗi được so sánh trong bước 4.
Lưu ý rằng đây không phải là trường hợp so sánh chuỗi khác , kể từ ví dụ WEISSBIER
và weißbier
có độ dài khác nhau nhưng cùng một từ viết hoa khác nhau, vì vậy so sánh phân biệt chữ hoa chữ thường không thể sử dụng bước 3. Tất cả so sánh bình đẳng có thể thực hiện bước 1 và 2 như quy tắc được sử dụng luôn giữ, vì vậy bạn nên sử dụng chúng theo cách riêng của mình một số có thể thực hiện bước 3.
Do đó, mặc dù bạn sai khi cho rằng đó là tham chiếu chứ không phải là giá trị được so sánh, đúng là tham chiếu được so sánh đầu tiên dưới dạng cắt ngắn rất đáng kể. Cũng lưu ý rằng các chuỗi nội bộ (các chuỗi được đặt trong hồ bơi thực tập bằng cách biên dịch hoặc bằng cách gọi là string.Intern
được gọi) sẽ do đó kích hoạt cắt ngắn này thường xuyên. Đây sẽ là trường hợp trong đoạn mã trong ví dụ của bạn, vì trình biên dịch sẽ sử dụng cùng một tham chiếu trong mỗi trường hợp.
Nếu bạn biết rằng một chuỗi được tập trung, bạn có thể phụ thuộc vào điều này (chỉ cần làm kiểm tra bình đẳng tham khảo), nhưng ngay cả khi bạn không biết chắc chắn bạn có thể hưởng lợi từ nó (tham khảo kiểm tra bình đẳng sẽ cắt ngắn ít nhất đôi lúc).
Nếu bạn có một chuỗi các chuỗi nơi bạn muốn thử nghiệm một số trong số chúng thường xuyên, nhưng bạn không muốn kéo dài tuổi thọ của chúng trong bộ nhớ nhiều như thực tập, thì bạn có thể sử dụng XmlNameTable hoặc LockFreeAtomizer (sắp được đổi tên thành ThreadSafeAtomizer và tài liệu được chuyển thành http://hackcraft.github.com/Ariadne/documentation/html/T_Ariadne_ThreadSafeAtomizer_1.htm - lẽ ra phải được đặt tên cho hàm thay vì chi tiết triển khai ngay từ đầu).
Giá trị cũ được sử dụng trong nội bộ XmlTextReader
và do đó có rất nhiều phần còn lại của System.Xml
và có thể được sử dụng bởi mã khác. Sau này tôi đã viết vì tôi muốn có một ý tưởng tương tự, đó là an toàn cho các cuộc gọi đồng thời, cho các loại khác nhau, và nơi tôi có thể ghi đè so sánh bình đẳng.
Trong cả hai trường hợp, nếu bạn đặt 50 chuỗi khác nhau là tất cả "abc" vào nó, bạn sẽ nhận được một tham chiếu "abc" duy nhất cho phép những người khác được thu gom rác. Nếu bạn biết điều này đã xảy ra, bạn có thể phụ thuộc vào ReferenceEquals
một mình và nếu bạn không chắc chắn, bạn sẽ vẫn được hưởng lợi từ việc cắt ngắn khi xảy ra sự cố.
@EricJ. Nhưng nếu chúng có cùng một địa chỉ bộ nhớ thì ** ** phải có nội dung giống nhau (sau cùng là * cùng *). – Yuck
@Yuck - Chỉ khi thực tập là một phần của thông số kỹ thuật và không chỉ là chi tiết triển khai. Ngoài ra, các chuỗi trong tên miền ứng dụng riêng biệt có thể bằng nhau và có địa chỉ khác nhau. – psr
@psr Đúng, đó là lý do tại sao kiểm tra có điều kiện. Nếu tham chiếu là như nhau thì bạn đã hoàn thành - đó là nó. Nếu không, bạn phải so sánh nội dung của mỗi biến để xác định sự bình đẳng logic. – Yuck