Jak mogę porównać ciąg znaków bez rozróżniania wielkości liter?


217

Jak mogę sprawić, aby wiersz poniżej nie rozróżniał wielkości liter?

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

Dostałem dzisiaj kilka porad, które sugerują, żebym użył:

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

Problem w tym, że nie mogę tego uruchomić. Wypróbowałem poniższy wiersz, który się kompiluje, ale zwraca nieprawidłowe wyniki, zwraca zarejestrowanych użytkowników jako niezarejestrowanych i niezarejestrowanych użytkowników jako zarejestrowanych.

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

Czy ktoś może wskazać problem?


1
Jaki powinien drUser["Enrolled"]być typ danych ? Wygląda jak wartość logiczna, ale FindIndex()zwraca indeks. Jeśli indeks tego użytkownika wynosi 0, wówczas zwróci 0, co może być fałszem. Kiedy w rzeczywistości jest prawdą. W Exists()tym przypadku metoda może być lepsza.
drharris

Czy na pewno nie ma czasu na formatowanie ani dodatkowego miejsca w jednym polu, którego nie ma w drugim?
joshlrogers

1
Sugerowałbym użycie enrolledUsers.Any () zamiast FindIndex (i test).
Marc

Odpowiedzi:


405

To nie jest najlepsza praktyka w .NET Framework (4 i +) do sprawdzania równości

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

Zamiast tego użyj następujących

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

MSDN zaleca:

  • Użyj przeciążenia metody String.Equals, aby sprawdzić, czy dwa łańcuchy są równe.
  • Użyj metod String.Compare i String.CompareTo do sortowania ciągów, a nie sprawdzania równości .

8
Powinieneś użyć string.Compare, nie String.Compare.
Fred

5
@Fred Zgadzam się, ale czy możesz określić powód?
Gusdor

22
@Fred Miałem nadzieję z przyczyn technicznych, a nie „ponieważ Stylecop tak mówi”. Czy coś brakuje?
Gusdor

12
bez różnicy string.compare z String.Compare, synonimy string Klasa System.String. i porównanie członków jest metodą rozszerzenia. @ Fred @Gusdor
Nuri YILMAZ

23
@Gusdor stringjest lepszą praktyką niż Stringponieważ jest słowem kluczowym dla języka. Po pierwsze, Stringmoże być czymś innym niż System.String, podczas gdy stringnie może być. Ponadto stringjest mniej więcej gwarantowane, że istnieje w języku C #, podczas gdy Stringtechnicznie jest częścią .NET, a nie C #.
Dave Cousineau,

36

Powinieneś użyć String.Comparefunkcji statycznej jak poniżej

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

6
Nie, powinieneś użyć String.Equalszamiast String.Compare. Nie ma potrzeby obliczania, który z nich jest większy, tylko że nie są one równe.
ErikE

@ErikE: Zastanawiam się, którą metodę zalecisz za 6 lat więcej :-)
Oleg

3
Nie zastanawiam się! Jestem pewien, że zalecę stosowanie równości, jeśli chcesz semantyki równości, i porównywanie, jeśli chcesz semantyki porównania. Co jest w tym takiego trudnego? IEquatablei IComparableNIE rób tego samego, i możesz mieć klasy, które implementują jedną, ale w których nie ma sensu implementować drugiej. Na przykład można zamówić próbki próbek według czasu, przy czym żadne z nich nie będzie równe (IComparable). I możesz wskazać, czy rzeczy są równe (IEquatable), ale nie ma sensu ich porządkować (powiedzmy, numery seryjne komputera).
ErikE

@ErikE: Nie rozumiesz mojego punktu widzenia. Stare odpowiedzi odpowiadają czasowi pisania. Nie należy dotykać starych odpowiedzi. Dotyczy to większości produktów. Najlepsze praktyki lub najlepszy wybór z punktu widzenia wydajności można zmienić wiele razy później. Nie widzę sensu rozmawiać o żadnej starej odpowiedzi.
Oleg

18
Przepraszam, wziąłem to za krytykę poprawności mojego komentarza. Jeśli mówisz, że przyznajesz, że twoja stara odpowiedź może nie być najlepsza, to świetnie! Jednak muszę się z tobą nie zgodzić co do starych odpowiedzi. Stare odpowiedzi, które dostarczają złych informacji, powinny zostać skomentowane, powinny zostać odrzucone, ponieważ wciąż informują dzisiejszych czytelników.
ErikE

27

Użyj tego do porównania:

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

10
Wystarczy pamiętać o zaletach i pułapkach korzystania z CurrentCultureIgnoreCase vs. OrdinalIgnoreCase. Jeśli nie potrzebujesz semantyki porównywania kultur, zaoszczędź trochę wydajności i użyj porównania porządkowego.
ErikE

7

Inne odpowiedzi są tutaj całkowicie poprawne, ale jakoś zajmuje trochę czasu, aby pisać StringComparison.OrdinalIgnoreCasei używać String.Compare.

Kodowałem prostą metodę rozszerzenia Ciągu, w której można określić, czy w porównaniu rozróżniana jest wielkość liter, czy też nie ma sensu wielkość logiczna, dołączając tutaj cały fragment kodu:

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;
    }
}

Po tym całe porównanie skraca się w przybliżeniu o 10 znaków - porównaj:

Przed użyciem rozszerzenia String:

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

Po użyciu rozszerzenia String:

testFilename.CompareTo(testToStart, true)

2
Nie zgadzam się z nazewnictwem, porównywanie jest dobrze znaną funkcją w programistach i zasadniczo zmieniłeś to, co robi. Myślę, że powinieneś albo zwrócić int jak porównać lub zmienić nazwę na coś innego, na przykład „IsEqual”.
Fred

7

Można (choć kontrowersyjnie) rozszerzyć, System.Stringaby zapewnić metodę rozszerzenia porównania bez rozróżniania wielkości liter:

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

i użyj jako takiego:

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

C # pozwala tworzyć metody rozszerzeń, które mogą służyć jako narzędzie do tworzenia składni w twoim projekcie, co byłoby całkiem przydatne.

To nie jest odpowiedź i wiem, że to pytanie jest stare i rozwiązane, chciałem tylko dodać te bity.


3

Myślę, że znajdziesz więcej informacji w tym linku:

http://codeidol.com/community/dotnet/controlling-case-sensitivity-when-comparing-two-st/8873/

Użyj metody statycznej Porównaj w klasie String, aby porównać dwa ciągi. To, czy porównanie nie uwzględnia wielkości liter, zależy od trzeciego parametru jednego z jego przeciążeń. Na przykład:

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

Wartość caseSensitiveResult wynosi -1 (wskazując, że lowerCase jest „mniejsza niż” upperCase), a caseInsensitiveResult ma wartość zero (wskazując, że lowerCase „równa się” upperCase).



1

Chciałbym napisać metodę rozszerzenia dla EqualsIgnoreCase

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

-11

zawsze możesz użyć funkcji: .ToLower (); .ToUpper ();

przekonwertować ciągi, a następnie porównać je ...

Powodzenia


Nie sądzę, żeby to rozwiązało jego problem. Zaznacz także, że to pytanie ma już ponad 4 lata.
Vojtěch Dohnal

7
To tworzy nowy ciąg, więc uważam to za bardzo nieefektywne. Ponieważ aby utworzyć ten nowy ciąg, wszystkie znaki zostaną sprawdzone i zamienione na pożądaną wielkość liter, dlatego porównanie musi ponownie sprawdzić wszystkie znaki. Dlatego zużywa więcej pamięci i mocy obliczeniowej.
Air2

5
Jest to bardzo zła praktyka ze względu na przydział pamięci.
Thorbjørn Lindeijer

Jest to nie tylko niepotrzebne przydzielanie pamięci i nieefektywne; również nie przejdzie testu Turcji .
dmitry
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.