Làm thế nào tôi có thể làm một trường hợp so sánh chuỗi không nhạy cảm?


217

Làm thế nào tôi có thể làm cho dòng dưới đây không nhạy cảm?

drUser["Enrolled"] = 
      (enrolledUsers.FindIndex(x => x.Username == (string)drUser["Username"]) != -1);

Tôi đã được đưa ra một số lời khuyên sớm hôm nay mà đề nghị tôi sử dụng:

x.Username.Equals((string)drUser["Username"], StringComparison.OrdinalIgnoreCase)));

vấn đề là tôi không thể làm việc này được, tôi đã thử dòng dưới đây, nó biên dịch nhưng trả về kết quả sai, nó trả về người dùng đã đăng ký là người dùng không được kiểm soát và không được kiểm soát như đã đăng ký.

drUser["Enrolled"] = 
      (enrolledUsers.FindIndex(x => x.Username.Equals((string)drUser["Username"], 
                                 StringComparison.OrdinalIgnoreCase)));

Bất cứ ai có thể chỉ ra vấn đề?


1
Những loại dữ liệu nên drUser["Enrolled"]được? Nó trông giống như một giá trị boolean, nhưng FindIndex()trả về chỉ mục. Nếu chỉ số của người dùng đó là 0, thì nó sẽ trả về 0, có thể là sai. Khi, trong thực tế là đúng. Các Exists()phương pháp có thể được tốt hơn trong trường hợp này.
drharris

Bạn có chắc chắn không có thời gian định dạng hoặc không gian thêm trong một trường không thuộc lĩnh vực kia không?
joshlrogers

1
Tôi khuyên bạn nên sử dụng những người đã đăng ký. Mọi người () thay vì Find Index (và kiểm tra).
Marc

Câu trả lời:


405

Đây không phải là cách thực hành tốt nhất trong .NET framework (4 & +) để kiểm tra sự bằng nhau

String.Compare(x.Username, (string)drUser["Username"], 
                  StringComparison.OrdinalIgnoreCase) == 0

Sử dụng như sau thay thế

String.Equals(x.Username, (string)drUser["Username"], 
                   StringComparison.OrdinalIgnoreCase) 

MSDN khuyến nghị:

  • Sử dụng quá tải phương thức String.Equals để kiểm tra xem hai chuỗi có bằng nhau không.
  • Sử dụng String.CompareString.CompareTo phương pháp để sắp xếp chuỗi, không để kiểm tra bình đẳng .

8
Bạn nên sử dụng string.Compare, không String.Compare.
Fred

5
@Fred Tôi đồng ý nhưng bạn có thể đủ điều kiện lý do?
Gusdor

22
@Fred Tôi đã hy vọng cho một lý do kỹ thuật hơn là 'vì Stylecop nói như vậy'. Tui bỏ lỡ điều gì vậy?
Gusdor

12
không có sự khác biệt String.compare với String.Compare, chuỗi từ đồng nghĩa lớp System.String. và thành viên So sánh là một phương thức mở rộng. @ Fred @Gusdor
Nuri

23
@Gusdor stringlà cách thực hành tốt hơn Stringvì nó là một từ khóa ngôn ngữ. Đối với một, Stringcó thể là một cái gì đó khác hơn System.String, trong khi stringkhông thể. Ngoài ra, stringít nhiều được đảm bảo tồn tại trong C #, trong khi Stringvề mặt kỹ thuật là một phần của .NET chứ không phải là C #.
Dave Cousineau

36

Bạn nên sử dụng String.Comparehàm tĩnh như sau

x => String.Compare (x.Username, (string)drUser["Username"],
                     StringComparison.OrdinalIgnoreCase) == 0

6
Không, bạn nên sử dụng String.Equalsthay vì String.Compare. Không cần phải tính toán cái nào lớn hơn, chỉ là chúng không bằng nhau.
ErikE

@ErikE: Tôi tự hỏi, phương pháp nào bạn sẽ khuyên bạn nên sử dụng trong 6 năm nữa :-)
Oleg

3
Tôi không thắc mắc! Tôi tự tin tôi sẽ khuyên bạn nên sử dụng bình đẳng khi bạn muốn ngữ nghĩa bình đẳng và sử dụng so sánh khi bạn muốn ngữ nghĩa so sánh. Có gì khó khăn về điều đó? IEquatableIComparableKHÔNG làm điều tương tự, và bạn có thể có các lớp thực hiện một lớp nhưng trong đó sẽ không có ý nghĩa gì khi thực hiện lớp kia. Ví dụ: bạn có thể yêu cầu lấy mẫu cảm biến theo thời gian mà không có bất kỳ cái nào bằng nhau (IComparable). Và, bạn có thể cho biết liệu mọi thứ có bằng nhau hay không (IEquitable) nhưng không có nghĩa gì khi đặt hàng chúng (giả sử, số sê-ri máy tính).
ErikE

@ErikE: Bạn không hiểu quan điểm của tôi. Câu trả lời cũ tương ứng với thời gian viết. Người ta không nên chạm vào câu trả lời cũ. Đó là sự thật về hầu hết các sản phẩm. Thực tiễn tốt nhất hoặc sự lựa chọn tốt nhất từ ​​quan điểm hiệu suất có thể được thay đổi nhiều lần sau đó. Tôi thấy không có ý nghĩa để thảo luận về bất kỳ câu trả lời cũ.
Oleg

18
Tôi xin lỗi, tôi đã coi đó là một bài phê bình về tính đúng đắn của nhận xét của tôi. Nếu những gì bạn đang nói là bạn thừa nhận câu trả lời cũ của bạn có thể không phải là câu trả lời hay nhất, thì thật tuyệt! Tuy nhiên, tôi phải không đồng ý với bạn về những câu trả lời cũ. Những câu trả lời cũ cung cấp thông tin kém nên được bình luận, nên bỏ phiếu xuống, bởi vì họ vẫn đang thông báo cho độc giả ngày nay .
ErikE

27

Vui lòng sử dụng để so sánh:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

10
Chỉ cần lưu ý về những lợi ích và cạm bẫy của việc sử dụng CurrentCARMIgnoreCase so với OrdinalIgnoreCase. Nếu bạn không cần ngữ nghĩa của so sánh văn hóa, hãy lưu một số hiệu suất và sử dụng so sánh thứ tự.
ErikE

7

Những người khác trả lời là hoàn toàn hợp lệ ở đây, nhưng bằng cách nào đó phải mất một thời gian để gõ StringComparison.OrdinalIgnoreCasevà cũng sử dụng String.Compare.

Tôi đã mã hóa phương thức mở rộng Chuỗi đơn giản, trong đó bạn có thể chỉ định nếu so sánh là phân biệt chữ hoa chữ thường hoặc chữ hoa chữ thường với boolean, đính kèm toàn bộ đoạn mã ở đây:

using System;

/// <summary>
/// String helpers.
/// </summary>
public static class StringExtensions
{
    /// <summary>
    /// Compares two strings, set ignoreCase to true to ignore case comparison ('A' == 'a')
    /// </summary>
    public static bool CompareTo(this string strA, string strB, bool ignoreCase)
    {
        return String.Compare(strA, strB, ignoreCase) == 0;
    }
}

Sau đó, toàn bộ so sánh rút ngắn khoảng 10 ký tự - so sánh:

Trước khi sử dụng chuỗi mở rộng:

String.Compare(testFilename, testToStart,true) != 0

Sau khi sử dụng chuỗi mở rộng:

testFilename.CompareTo(testToStart, true)

2
Tôi không đồng ý với việc đặt tên, so sánh là một chức năng nổi tiếng trong nhà phát triển phần mềm và về cơ bản bạn đã thay đổi những gì nó làm. Tôi nghĩ bạn nên trả lại một int như so sánh hoặc thay đổi tên thành một cái gì đó khác, ví dụ như 'IsEqual'.
Fred

7

Bạn có thể (mặc dù đối lập) mở rộng System.Stringđể cung cấp phương pháp mở rộng so sánh không phân biệt chữ hoa chữ thường:

public static bool CIEquals(this String a, String b) {
    return a.Equals(b, StringComparison.CurrentCultureIgnoreCase);
}

và sử dụng như vậy:

x.Username.CIEquals((string)drUser["Username"]);

C # cho phép bạn tạo các phương thức mở rộng có thể đóng vai trò là suggar cú pháp trong dự án của bạn, khá hữu ích mà tôi muốn nói.

Đó không phải là câu trả lời và tôi biết câu hỏi này đã cũ và đã được giải quyết, tôi chỉ muốn thêm các bit này.


3

Tôi nghĩ bạn sẽ tìm thấy thêm thông tin trong liên kết này:

http://codeidol.com/community/dotnet/controlling-case-sensergy-when-compared-two-st/8873/

Sử dụng phương thức So sánh tĩnh trên lớp Chuỗi để so sánh hai chuỗi. Việc so sánh có phân biệt chữ hoa chữ thường hay không được xác định bởi tham số thứ ba của một trong những quá tải của nó. Ví dụ:

string lowerCase = "abc";
string upperCase = "AbC";
int caseInsensitiveResult = string.Compare(lowerCase, upperCase,
  StringComparison.CurrentCultureIgnoreCase);
int caseSensitiveResult = string.Compare(lowerCase,
  StringComparison.CurrentCulture);

Giá trị caseSensitiveResult là -1 (chỉ ra rằng lowCase là "nhỏ hơn" UpperCase) và caseInsensitiveResult bằng 0 (chỉ ra rằng LowerCase "bằng" UpperCase).


1

Làm thế nào về việc sử dụng StringComparison.CurrentCultureIgnoreCasethay thế?


5
-1: Câu trả lời này là không đủ. Vui lòng xem câu trả lời của @ Ocean4dream: stackoverflow.com/a/13965429/109941 .
Jim G.

@decyclone: ​​Nó chậm hơn OrdinalIgnoreCase, nhưng có thể có liên quan trong một số trường hợp. Vì vậy, tôi sẽ không cho -1. stackoverflow.com/questions/2749662/
Mạnh


1

Tôi muốn viết một phương thức mở rộng cho EqualsIgnoreCase

public static class StringExtensions
{
    public static bool? EqualsIgnoreCase(this string strA, string strB)
    {
        return strA?.Equals(strB, StringComparison.CurrentCultureIgnoreCase);
    }
}

-11

bạn luôn có thể sử dụng các hàm: .ToLower (); .ToUpper ();

chuyển đổi chuỗi của bạn và sau đó so sánh chúng ...

Chúc may mắn


Tôi không nghĩ rằng điều này sẽ giải quyết vấn đề của mình. Cũng đánh dấu rằng câu hỏi này đã hơn 4 tuổi.
Vojtěch Dohnal

7
Điều này tạo ra một chuỗi mới, vì vậy tôi cho rằng điều này rất không hiệu quả. Bởi vì để tạo chuỗi mới này, tất cả các ký tự sẽ được kiểm tra và chuyển đổi sang trường hợp mong muốn, sau đó phép so sánh phải kiểm tra lại tất cả các ký tự. Vì vậy, nó sử dụng nhiều bộ nhớ và sức mạnh xử lý.
Air2

5
Đây là thực tế rất xấu vì phân bổ bộ nhớ.
Thorbjørn Lindeijer

Không chỉ đây là phân bổ bộ nhớ không cần thiết và không hiệu quả; nó cũng thất bại trong bài kiểm tra của Thổ Nhĩ Kỳ .
dmitry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.