2009-05-13 55 views
17

Có một số cách để so sánh chuỗi. Có hiệu suất đạt được bằng cách làm theo cách khác hơn?Hiệu suất so sánh chuỗi trong C#

Tôi luôn chọn để so sánh chuỗi như vậy:

string name = "Bob Wazowski"; 
if (name.CompareTo("Jill Yearsley") == 0) { 
    // whatever... 
} 

Nhưng tôi thấy rất ít người làm điều này, và nếu bất cứ điều gì, tôi thấy nhiều người chỉ làm một so sánh == thẳng, để kiến ​​thức của tôi là cách tồi tệ nhất để so sánh chuỗi. Liệu tôi có sai?

Ngoài ra, nó có tạo sự khác biệt về cách so sánh chuỗi trong các truy vấn LINQ không? Ví dụ: Tôi muốn thực hiện những việc sau:

var results = from names in ctx.Names 
       where names.FirstName.CompareTo("Bob Wazowski") == 0 
       select names; 

Nhưng một lần nữa, tôi thấy rất ít người so sánh chuỗi như vậy trong truy vấn LINQ của họ.

+0

thể trùng lặp của [Sự khác biệt trong chuỗi so sánh các phương pháp trong C#] (http://stackoverflow.com/questions/44288/differences-in-string-compare-methods-in-c-sharp) – crowder

+0

Bạn có thể muốn để xem http://rhale78.wordpress.com/2011/05/16/string-equality-and-performance-in-c/ – nawfal

Trả lời

22

Theo Reflector

"Hello" == "World" 

cũng giống như

String.Equals("Hello", "World"); 

mà về cơ bản xác định nếu họ là những đối tượng cùng tham khảo, nếu một trong hai trong số họ là null, đó sẽ là một tự động false nếu một là null và cái kia thì không, và sau đó so sánh từng ký tự trong một vòng lặp không an toàn. Vì vậy, nó không quan tâm đến các quy tắc văn hóa ở tất cả, mà thường không phải là một việc lớn.

"Hello".CompareTo("World") == 0 

cũng giống như

CultureInfo.CurrentCulture.CompareInfo.Compare("Hello", "World", CompareOptions.None); 

này về cơ bản là điều ngược lại như xa như chức năng. Nó đưa vào xem xét văn hóa, mã hóa và mọi thứ khác với chuỗi trong ngữ cảnh.

Vì vậy, tôi sẽ tưởng tượng rằng String.CompareTo là một vài đơn đặt hàng có cường độ chậm hơn so với toán tử bình đẳng.

như đối với LINQ của bạn nó không quan trọng nếu bạn đang sử dụng LINQ-to-SQL vì cả hai sẽ tạo ra SQL cùng

var results = from names in ctx.Names 
      where names.FirstName.CompareTo("Bob Wazowski") == 0 
      select names; 

của

SELECT [name fields] 
FROM [Names] AS [t0] 
WHERE [t0].FirstName = @p0 

vì vậy bạn thực sự không phải là đạt được bất cứ điều gì cho LINQ-to-SQL ngoại trừ khó đọc mã và có thể phân tích cú pháp hơn về các biểu thức. Nếu bạn chỉ sử dụng LINQ cho các công cụ mảng chuẩn thì các quy tắc tôi đã nêu ở trên sẽ được áp dụng.

+2

string.Equals không thực hiện kiểm tra bình đẳng tham chiếu trong .NET 4.0, nó bị quá tải trong chuỗi để so sánh các chuỗi thực tế. (Tôi sẽ không ngạc nhiên nếu điều này luôn luôn đúng.) – Massif

+0

AFAIK, string.Equals cũng xem xét văn hóa. –

+1

@ Massif trả lời là chính xác. String.Equals() và == không so sánh tham chiếu đối tượng. Để chứng minh nó cho chính bạn, hãy gọi Object.ReferenceEquals (x, y), trong đó x là hardcoded string và y được đưa ra trên dòng lệnh. – GreenRibbon

2

Có một câu hỏi tương tự gần đây liên quan đến cách nhanh nhất để cắt xâu chuỗi, nhưng về cơ bản nó là điểm chuẩn theo các cách khác nhau để so sánh chúng.

Bạn có thể xem các tiêu chí chuẩn on this post.

+0

Tôi đã xem bài đăng. Cảm ơn, nó rất hữu ích. Nó chỉ xác nhận lại rằng string.length là cách nhanh nhất để kiểm tra xem một chuỗi có trống không, trừ khi tôi hiểu lầm các kết quả benchmark. – Jagd

15

Theo ý kiến ​​của tôi, bạn nên luôn sử dụng cách rõ ràng nhất, đang sử dụng ==!

Điều này có thể được hiểu trực tiếp: Khi "Xin chào" bằng "Thế giới", hãy làm điều gì đó.

if ("Hello" == "World") 
    // ... 

Nội bộ, String::Equals được gọi rõ ràng tồn tại cho mục đích này - So sánh hai chuỗi để bình đẳng. (Điều này không liên quan gì đến con trỏ và tham chiếu, v.v.)

Điều này không rõ ràng ngay lập tức - Tại sao so sánh với số không?

if ("Hello".CompareTo("World") == 0) 

.CompareTo không được thiết kế chỉ để kiểm tra sự bình đẳng (bạn đã == cho việc này) - Nó so sánh hai chuỗi. Bạn sử dụng .CompareTo trong các loại để xác định wheter một chuỗi là "lớn hơn" khác. Bạn có thể kiểm tra tính bình đẳng bởi vì nó mang lại số không cho các chuỗi bằng nhau, nhưng đó không phải là những gì nó được khái niệm.

Do đó có những phương pháp khác nhau và giao diện để kiểm tra sự bình đẳng (IEquatable, toán tử ==) và so sánh (IComparable)

LINQ không cư xử khác với thường xuyên C# đây.

+2

OP không hỏi về cách nào là cách rõ ràng nhất để viết so sánh chuỗi. Điều rõ ràng đối với một người có thể không rõ ràng với người khác. –

8

Đọc Jeff's The Best Code is No Code at All. foo.CompareTo(bar) == 0: sự lộn xộn hình ảnh khủng khiếp. Mất rất nhiều không gian và truyền tải không có ý nghĩa thú vị. Trong thực tế, nó nhấn mạnh rất nhiều thứ không liên quan làm giảm sự chú ý khỏi vấn đề thực sự.

Nếu không có lý do chính xác để sử dụng biến thể dài hơn này thì không.

Đối với hiệu suất: nó chỉ đơn giản là không quan trọng đối với trường hợp đơn giản này. Nếu nhà điều hành bình đẳng == thực sự hoạt động kém hơn CompareTo, vui lòng gửi báo cáo lỗi với Microsoft. Điều này không được xảy ra.

1

Nếu nhà điều hành bình đẳng thực sự hoạt động kém hơn CompareTo - Microsoft sẽ không thực hiện cuộc gọi điều hành bình đẳng CompareTo?

Chỉ cần sử dụng toán tử bình đẳng để kiểm tra tính bình đẳng.

0

Tôi thường sử dụng String.Compare với quá tải nhận tham số StringComparison, vì sau đó tôi có thể hoàn toàn rõ ràng về việc liệu so sánh có phân biệt chữ hoa và chữ thường hay không. Điều này cần .NET 2.0 hoặc mới hơn.

Nhanh nhất là StringComparison.Ordinal (hoặc StringComparison.OrdinalIgnoreCase nếu không phân biệt chữ hoa chữ thường) để so sánh không nhạy cảm với văn hóa.

Vấn đề với việc sử dụng == là không rõ ràng tác giả đã xem xét độ nhạy trường hợp và văn hóa hay không.

Có một bài viết MSDN tốt về chủ đề here.

+0

== bằng Equals(), và Equals() làm cho CaseSens. & CultureInsens. tìm kiếm (nhanh nhất, dễ nhớ). Calling Equals (var, StringComparison.OrdinalCaseInsensetive) là chậm hơn so với gọi Equals() vì vậy trong trường hợp u're so sánh hàng triệu chuỗi tốt hơn để sử dụng đơn giản Equals() thay vì == và 2arg phiên bản. – Grigory

0

Để Cách tốt nhất để so sánh string 's trong C# là sử dụng a.Equals(b) nơi mộtb là chuỗi.Đây là cách tốt nhất để so sánh chuỗi vì nó so sánh giá trị của các đối tượng ab và không phụ thuộc vào tham chiếu của đối tượng.

Nếu bạn định sử dụng biểu tượng "==", kết quả sẽ bằng nhau nếu cả hai đối tượng có cùng tham chiếu nhưng bạn sẽ gặp sự cố khi chúng có tham chiếu khác nhau và có cùng giá trị.

Phương pháp compareTo là cách tốt nhất để sử dụng nếu thử nghiệm của bạn cho dù các chuỗi khác trước, sau hoặc xuất hiện ở vị trí tương tự của chuỗi khác trong đó nó sẽ trở lại giá trị âm, giá trị tích cực hoặc không có giá trị tương ứng. Nó sẽ trở lại giá trị cũng tích cực nếu tham số là null

+0

Rõ ràng đã có từ các câu trả lời khác nhưng chỉ để đảm bảo: điều này là sai. chuỗi quá tải toán tử '==' –

4

Vâng MSDN khẳng định bạn shoul sử dụng chức năng so sánh theo công việc bạn cần phải thực hiện:

Phương pháp CompareTo được thiết kế chủ yếu để sử dụng trong phân loại hoặc hoạt động theo thứ tự bảng chữ cái. Nó không nên được sử dụng khi mục đích chính của cuộc gọi phương thức là xác định xem hai chuỗi có tương đương hay không. Để xác định xem hai chuỗi có tương đương hay không, hãy gọi phương thức Equals.

Vì vậy, nếu nó không phải là về phân loại và giá trị retrun là không quan trọng tôi sẽ nói ta nên sử dụng:

first.Equals(second) hoặc nếu so sánh là văn hóa cụ thể ví dụ như trong các ngôn ngữ như ở Đức:

String.Equals(first, second, StringComparison.CurrentCulture)

Hãy xem một những liên kết này:

How to: Compare Strings (C# Programming Guide)

String.CompareTo Method (Object)

0

Here là hướng dẫn MSDN đầy đủ nhất và hữu ích để so sánh chuỗi Tôi đã được tìm thấy.

Sử dụng so sánh với StringComparison.Ordinal hoặc StringComparison.OrdinalIgnoreCase để có hiệu suất tốt hơn.

Các vấn đề liên quan