Как я могу сделать сравнение строк без учета регистра?


217

Как сделать строку ниже без учета регистра?

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

Сегодня мне дали несколько советов, которые предложили мне использовать:

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

проблема в том, что я не могу заставить это работать, я попробовал строку ниже, она компилируется, но возвращает неправильные результаты, она возвращает зарегистрированных пользователей как незарегистрированных и незарегистрированных пользователей как зарегистрированных.

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

Кто-нибудь может указать на проблему?


1
Какой тип данных должен drUser["Enrolled"]быть? Это выглядит как логическое значение, но FindIndex()возвращает индекс. Если индекс этого пользователя равен 0, он вернет 0, что может быть ложным. Когда на самом деле это правда. Exists()Метод может быть лучше в этом случае.
drharris

Вы уверены, что в одном поле нет времени или лишнего пробела, которого нет в другом?
Joshlrogers

1
Я бы предложил использовать enrolledUsers.Any () вместо FindIndex (и test).
Марк

Ответы:


405

Это не лучшая практика в .NET Framework (4 & +) для проверки равенства

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

Используйте следующее вместо

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

MSDN рекомендует:

  • Используйте перегрузку метода String.Equals, чтобы проверить, равны ли две строки.
  • Используйте методы String.Compare и String.CompareTo для сортировки строк, а не для проверки на равенство .

8
Вы должны использовать string.Compare, а не String.Compare.
Фред

5
@ Фред, я согласен, но ты можешь определить причину?
Гусдор

22
@ Фред Я надеялся по технической причине, а не «потому что так говорит Стикоп». Я что-то упускаю?
Гусдор

12
без разницы string.compare со String.Compare, строковые синонимы класса System.String. и член Compare - это метод расширения. @ Fred @Gusdor
Нури ИЛМАЗ

24
@Gusdor string- лучшая практика, чем Stringключевое слово языка. С одной стороны, Stringможет быть что-то другое System.String, а stringне может быть. Кроме того, stringболее или менее гарантированно существует в C #, тогда Stringкак технически является частью .NET, а не C #.
Дэйв Кузино

36

Вы должны использовать статическую String.Compareфункцию, как показано ниже

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

6
Нет, вы должны использовать String.Equalsвместо String.Compare. Нет необходимости вычислять, какой из них больше, просто они не равны.
ErikE

@ErikE: Мне интересно, какой метод вы порекомендуете использовать еще через 6 лет :-)
Олег

3
Я не удивляюсь! Я уверен, что я рекомендую использовать равенство, когда вы хотите семантику равенства, и использовать сравнение, когда вы хотите семантику сравнения. Что в этом такого сложного? IEquatableи IComparableНЕ делайте то же самое, и у вас могут быть классы, которые реализуют один, но в котором не имеет смысла реализовывать другой. Например, вы можете упорядочить выборки датчиков по времени, не имея при этом равных (IComparable). И вы можете указать, равны ли вещи (IEquatable), но нет смысла заказывать их (скажем, серийные номера компьютера).
ErikE

@ErikE: Вы не понимаете мою точку зрения. Старые ответы соответствуют времени написания. Не нужно трогать старые ответы. Это правда о большинстве продуктов. Лучшая практика или лучший выбор с точки зрения производительности могут быть изменены несколько раз позже. Не вижу смысла обсуждать какой-либо старый ответ.
Олег

18
Мои извинения, я воспринял это как критику правильности моего комментария. Если вы говорите, что признаете, что ваш старый ответ не самый лучший, то отлично! Тем не менее, я должен не согласиться с вами по поводу старых ответов. Старые комментарии, которые дают плохую информацию, должны быть прокомментированы, должны быть понижены, потому что они все еще информируют сегодняшних читателей.
ErikE

28

Пожалуйста, используйте это для сравнения:

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

11
Просто помните о преимуществах и недостатках использования CurrentCultureIgnoreCase по сравнению с OrdinalIgnoreCase. Если вам не нужна семантика сравнения культур, сохраните производительность и используйте порядковый порядок сравнения.
ErikE

7

Другие ответы здесь полностью действительны, но каким-то образом требуется некоторое время, чтобы напечатать, StringComparison.OrdinalIgnoreCaseа также использовать String.Compare.

Я написал простой метод расширения String, где вы можете указать, является ли сравнение чувствительным к регистру или бессмысленным с логическим значением, прикрепив здесь весь фрагмент кода:

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

После этого все сравнение укорачивается примерно на 10 символов - сравните:

Перед использованием расширения String:

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

После использования расширения String:

testFilename.CompareTo(testToStart, true)

2
Я не согласен с именами, сравнение - это хорошо известная функция в программном обеспечении, и вы в корне изменили то, что она делает. Я думаю, что вы должны либо вернуть int, например, сравнить или изменить имя на другое, например, IsEqual.
Фред

7

Вы можете (хотя и противоречиво) расширить, System.Stringчтобы предоставить метод расширения сравнения без учета регистра:

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

и используйте как таковой:

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

C # позволяет вам создавать методы расширения, которые могут служить синтаксическим сахаром в вашем проекте, я бы сказал, весьма полезно.

Это не ответ, и я знаю, что этот вопрос старый и решенный, я просто хотел добавить эти биты.


3

Я думаю, вы найдете больше информации по этой ссылке:

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

Используйте статический метод Compare в классе String, чтобы сравнить две строки. Является ли сравнение регистронезависимым, определяется третьим параметром одной из его перегрузок. Например:

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

Значение caseSensitiveResult равно -1 (указывает на то, что lowerCase «меньше, чем» upperCase), а caseInsensitiveResult равно нулю (указывает, что lowerCase «равно» upperCase).


1

Как насчет использования StringComparison.CurrentCultureIgnoreCaseвместо?


5
-1: этого ответа недостаточно. Пожалуйста, смотрите ответ @ ocean4dream: stackoverflow.com/a/13965429/109941 .
Джим Г.

@decyclone: ​​это медленнее, чем OrdinalIgnoreCase, но может быть уместно в некоторых случаях. Поэтому я не дам -1. stackoverflow.com/questions/2749662/…
Чаба Тот


1

Я хотел бы написать метод расширения для EqualsIgnoreCase

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

-11

Вы всегда можете использовать функции: .ToLower (); .ToUpper ();

преобразовать ваши строки, а затем сравнить их ...

Удачи


Я не думаю, что это решило бы его проблему. Также отметим, что этому вопросу уже более 4 лет.
Войтех Дональ

7
Это создает новую строку, поэтому я считаю это очень неэффективным. Поскольку для создания этой новой строки все символы будут проверены и преобразованы в нужный регистр, то при сравнении необходимо проверить все символы еще раз. Так что он использует больше памяти и вычислительной мощности.
Air2

5
Это очень плохая практика из-за выделения памяти.
Турбьёрн Линдейер,

Мало того, что это ненужное распределение памяти и неэффективно; это также не проходит испытание в Турции .
дмитрий
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.