Без учета регистра 'Contains (string)'

Есть ли способ сделать следующий возврат верным?

string title = "ASTRINGTOTEST";
title.Contains("string");

Кажется, не существует перегрузки, которая позволяет мне установить чувствительность к регистру. В настоящее время я ЗАПИСЫВАЮ ВЕРХНИЙ РЕГИСТР их обоих, но это просто глупо (под этим я имею в виду проблемы i18n, которые возникают с верхним и нижним регистром).

ОБНОВИТЬ
Это древний вопрос, и с тех пор я понял, что просил простого ответа на действительно обширную и сложную тему, если вы хотите исследовать ее полностью. В большинстве случаев в одноязычных, английских кодовых базах ответа это будет достаточно. Я подозреваю, потому что большинство людей, приезжающих сюда, попадают в эту категорию, это самый популярный ответ. Однако ответ Этот поднимает внутреннюю проблему, заключающуюся в том, что мы не можем сравнивать текст без учета регистра, пока не узнаем, что оба текста принадлежат к одной и той же культуре, и мы не знаем, что это за культура. Возможно, это менее популярный ответ, но я думаю, что он более правильный, и поэтому я отметил его как таковой.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3 075
0
969 791
28
Перейти к ответу Данный вопрос помечен как решенный

Ответы 28

Вы всегда можете сначала просто поднять или опустить струны.

string title = "string":
title.ToUpper().Contains("STRING")  // returns true

Ой, только что видел последнюю часть. При сравнении без учета регистра *, возможно, * в любом случае сделает то же самое, и если производительность не является проблемой, я не вижу проблем с созданием копий в верхнем регистре и их сравнением. Я мог бы поклясться, что однажды видел сравнение без учета регистра ...

Интересно, что я видел, как ToUpper () рекомендуется использовать вместо ToLower () в подобном сценарии, потому что, очевидно, ToLower () может «потерять точность» в определенных культурах, то есть два разных символа верхнего регистра переводятся в одно и то же строчный символ.

Matt Hamilton 15.01.2009 00:47

Ищите "тест индейки" :)

Jon Skeet 15.01.2009 00:48

В некоторых французских языках прописные буквы не имеют диакритических знаков, поэтому ToUpper () может быть ничем не лучше ToLower (). Я бы посоветовал использовать подходящие инструменты, если они доступны - сравнение без учета регистра.

Blair Conrad 15.01.2009 01:03

Не используйте ToUpper или ToLower и делайте то, что сказал Джон Скит

Peter Gfader 21.08.2009 06:49

Только что увидел это снова через два года и новое отрицательное голосование ... в любом случае, я согласен с тем, что есть более эффективные способы сравнения строк. Однако не все программы будут локализованы (большинство - нет), и многие из них являются внутренними или одноразовыми приложениями. Поскольку я не могу рассчитывать на то, что совет лучше всего оставить для одноразовых приложений ... Я двигаюсь дальше: D

Ed S. 25.01.2011 10:28

Даже если ваше приложение не локализовано, оно все равно может работать в затронутом регионе с действующей культурой локального потока и завершиться ошибкой.

ygoe 17.08.2015 21:04

@LonelyPixel: Я полагаю, я хотел сказать, что этот код не должен появляться ни в чем, кроме одноразового приложения. В таком случае, я не думаю, что тебе все равно.

Ed S. 18.08.2015 00:15

Поиск «теста Турции» - это то же самое, что поиск «теста Турции»?

JackAce 01.06.2018 19:24

@JackAce: зависит от приложения.

Ed S. 07.06.2018 01:12

Вы можете использовать String.IndexOf - метод и передать StringComparison.OrdinalIgnoreCase в качестве используемого типа поиска:

string title = "STRING";
bool contains = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;

Еще лучше определить новый метод расширения для строки:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source?.IndexOf(toCheck, comp) >= 0;
    }
}

Обратите внимание, что нулевое распространение?. доступен с C# 6.0 (VS 2015), для более старых версий используйте

if (source == null) return false;
return source.IndexOf(toCheck, comp) >= 0;

ПРИМЕНЕНИЕ:

string title = "STRING";
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);

Где лучше всего разместить что-то подобное в структуре приложения?

Andrew 18.11.2010 16:59

@Andi, у меня обычно есть пара файлов кода с методами расширения общего назначения, куда это могло бы пойти.

JaredPar 18.11.2010 20:29

@JaredPar: Мне любопытно узнать, есть ли это в .Net 4 или .Net 4.5, знаете ли вы?

VoodooChild 19.09.2011 19:52

@VoodooChild, похоже, это не так. Судя по листингу 4.0 API здесь msdn.microsoft.com/en-us/library/system.string_methods.aspx

JaredPar 19.09.2011 19:58

Кажется, не работает в запросах Entity Framework (4.x). Вероятно, потому что он находится в части LINQ to SQL. Я получаю следующую ошибку: LINQ to SQL не распознает метод Boolean Contains (System.String, System.String, System.StringComparison), и этот метод не может быть преобразован в выражение хранилища. Подзапрос, выполняемый после возврата результатов, работает. Я не думаю, что это имеет какое-либо отношение к расширению, поскольку LINQ to SQL не знает, как преобразовать код в SQL-запрос.

Roland Schaer 17.11.2011 20:16

есть справочный сайт для такого полезного расширения, чтобы поделиться преимуществом. эта запись очень похожа на эту extensionmethod.net/Details.aspx?ID=473

Michael Bahig 16.02.2012 14:56

Отличный метод расширения строки! Я отредактировал свой, чтобы проверить, что исходная строка не равна нулю, чтобы предотвратить возникновение ошибок ссылки на объект при выполнении .IndexOf ().

Richard Pursehouse 08.02.2013 14:48

@JookyDFW LINQ to SQL (и LINQ to Entities для базы данных SQL) будет использовать сравнение строк с использованием сортировки по умолчанию в вашей БД, которая в большинстве случаев нечувствительна к регистру, поэтому "СТРОКА" и "строка" совпадают при обращении к БД, но не совпадать по возвращаемым результатам без использования этого расширения.

Timothy Walters 12.02.2013 06:29

Это дает тот же ответ, что и paragraph.ToLower(culture).Contains(word.ToLower(culture)) с CultureInfo.InvariantCulture, и не решает никаких проблем с локализацией. Зачем все усложнять? stackoverflow.com/a/15464440/284795

Colonel Panic 17.03.2013 22:52

@ColonelPanic версия ToLower включает 2 выделения, которые не нужны при операции сравнения / поиска. Зачем без нужды выделять ресурсы в сценарии, который этого не требует?

JaredPar 18.03.2013 20:09

А как насчет LINQ IEnumerable.Contains, который позволяет указать параметр StringComparison, например StringComparison.CurrentCultureIgnoreCase? См. MSDN msdn.microsoft.com/en-us/library/bb339118(v=vs.95).aspx

seebiscuit 05.11.2014 19:02

@Seabiscuit, который не будет работать, потому что string - это IEnumerable<char>, поэтому вы не можете использовать его для поиска подстрок

JaredPar 06.11.2014 20:55

@fiat Раньше это был принятый ответ, но на самом деле это не совсем правильный ответ. Пока вы остаетесь в рамках стандартных латинских символов, это выглядит тривиальной разницей, но для большей части мира это не так. Проблема в том, что я попросил простой ответ на то, что, как я теперь знаю, является действительно сложной темой, и ответ действительно зависит от сценария. Я обновлю исходный вопрос, чтобы отразить это.

Boris Callens 26.08.2015 11:23

В качестве предпочтения стиля я бы просто добавил явный метод, а не перегрузку Contains: public static bool ContainsIgnoreCase (этот источник строки, строка toCheck) {return source.IndexOf (toCheck, StringComparison.OrdinalIgnoreCase)> = 0; }

What Would Be Cool 21.09.2015 17:45

@CodeBlend, скорее всего, они протестировали весь свой внутренний материал, который знает об их изменениях, и никто не проверял (или никого не заботил), что он сломал все внешние ссылки.

Chris Marisic 28.01.2016 21:17

Предупреждение: по умолчанию для string.IndexOf(string) используется текущая культура, а для string.Contains(string) по умолчанию используется порядковый компаратор. Как мы знаем, первое можно изменить, выбрав более длительную перегрузку, а второе изменить нельзя. Следствием этого несоответствия является следующий образец кода: Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string self = "Waldstrasse"; string value = "straße"; Console.WriteLine(self.Contains(value));/* False */ Console.WriteLine(self.IndexOf(value) >= 0);/* True */

Jeppe Stig Nielsen 18.02.2016 12:40

Нельзя расширить для нестатических универсальных классов ... разве это не проблема, по крайней мере, в 50% случаев для всех?

maplemale 06.12.2017 06:43

Как источник может быть нулевым? Это метод расширения.

Kyle Delaney 04.04.2018 17:38

Метод расширения @KyleDelaney this может иметь значение null. Хотелось бы, чтобы в C# была встроенная проверка на null, но ее нет.

Iain 22.05.2018 09:05

Я применил тот же метод расширения, однако вместо этого я проверил null в строке toCheck, если кодировщик передает нулевое значение, метод IndexOf все равно генерирует исключение ArgumentNullException. Таким образом, метод расширения может проверять как источник, так и toCheck на отказоустойчивость.

Tore Aurstad 29.06.2018 20:44

@Iain Если вы вызываете myString.SomeMethod(), а myString имеет значение null, вы действительно заслуживаете исключения для нулевого указателя. Проверять это - не задача метода расширения.

Nyerguds 19.12.2019 15:38

@Nyerguds нет, вызывая метод расширения по нулевому указателю работает. Меня это удивило, когда я впервые это увидел, но: shrug:

Iain 14.04.2020 10:01

@Iain Моя точка зрения остается неизменной; даже если это работает, это не задача метода, чтобы проверить это, потому что расширения должны действовать как обычные функции, выполняемые над объектом. Тем не менее, это, безусловно, полезно знать об этой маленькой причуде.

Nyerguds 14.04.2020 18:31

Вы можете использовать IndexOf() так:

string title = "STRING";

if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
{
    // The string exists in the original
}

Поскольку 0 (ноль) может быть индексом, вы проверяете значение -1.

MSDN

The zero-based index position of value if that string is found, or -1 if it is not. If value is String.Empty, the return value is 0.

Альтернативное решение с использованием Regex:

bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);

Хорошая идея, также у нас есть много побитовых комбинаций в RegexOptions, таких как RegexOptions.IgnoreCase & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant;, для всех, если это поможет.

Saravanan 24.08.2011 08:36

Должен сказать, что предпочитаю этот метод, хотя для наглядности использую IsMatch.

wonea 07.09.2011 21:40

Что еще хуже, поскольку строка поиска интерпретируется как регулярное выражение, ряд знаков пунктуации приведет к неверным результатам (или вызовет исключение из-за недопустимого выражения). Попробуйте поискать "." в "This is a sample string that doesn't contain the search string". Или попробуйте поискать "(invalid", если на то пошло.

cHao 09.09.2011 17:28

@cHao: В этом случае может помочь Regex.Escape. Регулярное выражение все еще кажется ненужным, когда IndexOf / extension Contains прост (и, возможно, более понятен).

Dan Mangiarelli 09.09.2011 20:44

Обратите внимание, что я не имел в виду, что это решение Regex было лучшим вариантом. Я просто добавлял в список ответов на исходный заданный вопрос «Есть ли способ сделать следующий возврат верным?».

Jed 13.09.2011 19:43

@cHao: спасибо, что выделили это, осветили. Тем не менее, я предпочитаю этот способ из-за неотъемлемой силы регулярных выражений.

wonea 15.09.2011 14:44

Это будет значительно менее эффективно, чем использование IndexOf. Использование Regex значительно увеличит время обработки, память и т. д.

Liam 15.09.2015 18:47

Поскольку это не работает в простых сценариях («.», «Здесь нет точки»), это нет - «альтернативное решение».

ANeves thinks SE is evil 21.07.2017 17:14

@Saravanan, вы перепутали И & с ИЛИ |, вместо этого должен быть RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant;.

Nekuś 17.07.2020 14:53

Класс StringExtension - это путь вперед, я объединил пару сообщений выше, чтобы дать полный пример кода:

public static class StringExtensions
{
    /// <summary>
    /// Allows case insensitive checks
    /// </summary>
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source.IndexOf(toCheck, comp) >= 0;
    }
}

почему вы разрешаете ДРУГОЙ уровень абстракции поверх StringComparison?

Alex Gordon 20.06.2019 21:37

Потому что это упрощает как чтение, так и написание кода. По сути, он имитирует то, что более поздние версии .Net добавили непосредственно в класс. Можно многое сказать о простых удобных методах, которые облегчают вашу жизнь и жизнь других, даже если они добавляют немного абстракции.

Josh 06.01.2021 14:08

Одна из проблем с ответом заключается в том, что он вызовет исключение, если строка имеет значение NULL. Вы можете добавить это как проверку, чтобы этого не произошло:

public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    if (string.IsNullOrEmpty(toCheck) || string.IsNullOrEmpty(source))
        return true;

    return source.IndexOf(toCheck, comp) >= 0;
} 

Если toCheck - пустая строка, она должна вернуть true согласно документации Contains: «true, если параметр value встречается в этой строке, или если value является пустой строкой (" "); в противном случае - false."

amurra 16.02.2011 19:13

Основываясь на приведенном выше комментарии Амурры, не нужно ли исправлять предлагаемый код? И не следует ли это добавить к принятому ответу, чтобы сначала был лучший ответ?

David White 30.08.2011 07:43

Теперь это вернет истину, если источник - пустая строка или ноль, независимо от того, что такое toCheck. Это не может быть правильным. Также IndexOf уже возвращает истину, если toCheck - пустая строка, а источник не равен нулю. Здесь нужна проверка на нуль. Я предлагаю if (source == null || value == null) return false;

Colin 01.07.2013 16:21

Источник не может быть нулевым

Lucas 14.12.2016 19:55
if (string.IsNullOrEmpty(source)) return string.IsNullOrEmpty(toCheck);
Kyle Delaney 04.04.2018 16:39

Итак, пустая строка содержит «Foo» ... как это правда?

bytedev 19.10.2018 13:21

Мне пришлось проголосовать против этого, а также еще 6 человек, это просто неправильно. должен быть return false;, а не return true;

Alex Gordon 20.06.2019 21:36

Использовать это:

string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);

Спрашивающий ищет Contains, а не Compare.

DuckMaestro 11.07.2011 12:05

@DuckMaestro, принятый ответ реализует Contains с IndexOf. Так что этот подход одинаково полезен! В примере кода C# на эта страница используется string.Compare (). Выбор команды SharePoint!

vulcan raven 05.01.2013 14:07

Знаю, что это не C#, но в фреймворке (VB.NET) уже есть такая функция

Dim str As String = "UPPERlower"
Dim b As Boolean = InStr(str, "UpperLower")

Вариант C#:

string myString = "Hello World";
bool contains = Microsoft.VisualBasic.Strings.InStr(myString, "world");

Это чисто и просто.

Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)

Однако это будет соответствовать шаблону. В вашем примере, если в fileNamestr есть какие-либо специальные символы регулярного выражения (например, *, +, . и т. д.), Вы будете приятно удивлены. Единственный способ заставить это решение работать как правильная функция Contains - это выйти из fileNamestr, выполнив Regex.Escape(fileNamestr).

XåpplI'-I0llwlg'I - 03.02.2013 19:18

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

phuclv 30.11.2019 08:51
Ответ принят как подходящий

Чтобы проверить, содержит ли строка paragraph строку word (спасибо @QuarterMeister)

culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0

Где culture - это экземпляр CultureInfo, описывающий язык, на котором написан текст.

Это решение прозрачно для определение нечувствительности к регистру, которое зависит от языка. Например, английский язык использует символы I и i для прописных и строчных версий девятой буквы, тогда как турецкий язык использует эти символы для одиннадцатая и двенадцатая буквы своего 29-буквенного алфавита. Версия «i» в турецком верхнем регистре - это незнакомый символ «İ».

Таким образом, строки tin и TIN - это одно и то же слово на английском, но разные слова в Турции. Насколько я понимаю, одно означает «дух», а другое - звукоподражательное слово. (Турки, поправьте меня, пожалуйста, если я ошибаюсь, или подскажите пример получше)

Подводя итог, вы можете ответить только на вопрос «являются ли эти две строки одинаковыми, но в разных случаях» если вы знаете, на каком языке написан текст. Если вы не знаете, вам придется покататься на лодке. Учитывая гегемонию английского языка в программном обеспечении, вам, вероятно, следует прибегнуть к CultureInfo.InvariantCulture, потому что он будет неправильным в привычных отношениях.

Я понимаю вашу точку зрения, и вы, вероятно, правы. Это старый вопрос, и мне нужно перечитать его еще раз, но я думаю, что изменю принятый ответ.

Boris Callens 18.03.2013 12:04

Почему не culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0? При этом используется правильный язык и региональные параметры, не учитывается регистр, не выделяются временные строчные строки, и не возникает вопроса о том, всегда ли преобразование в нижний регистр и сравнение аналогичны сравнению без учета регистра.

Quartermeister 18.03.2013 19:32

@Quartermeister, это сработает. Я попытался выяснить, как CompareInfo.IndexOf определяет сравнение без учета регистра, но этот метод просто обертывает недокументированный InternalFindNLSStringEx.

Colonel Panic 18.03.2013 19:41

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

JaredPar 18.03.2013 20:09

Сравнение с ToLower () даст разные результаты из-за нечувствительности к регистру IndexOf, когда две разные буквы имеют одну и ту же строчную букву. Например, вызов ToLower () для U + 0398 «греческая заглавная буква тета» или U + 03F4 «греческий заглавная буква тета» приводит к U + 03B8, «греческая строчная буква тета», но заглавные буквы считаются разными. В обоих решениях строчные буквы с одной и той же заглавной буквой различаются, например, U + 0073 «Латинская строчная буква S» и U + 017F «Латинская строчная длинная буква S», поэтому решение IndexOf кажется более последовательным.

Quartermeister 18.03.2013 21:47

Для FindNLSStringEx есть документация MSDN, которая, вероятно, применима к InternalFindNLSStringEx. Флаг - NORM_IGNORECASE, который «игнорирует любое третичное различие, независимо от того, действительно ли это лингвистический случай», но я недостаточно знаю о NLS, чтобы понять, что такое «третичное различие».

Quartermeister 18.03.2013 21:53

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

kutschkem 22.03.2013 23:08

@Quartermeister - третичное различие - это регистр. Может быть лингвистическим (турецкий i -> İ) или нет (ascii i -> I). Определение можно найти на сайте oracle: docs.oracle.com/cd/B28359_01/server.111/b28298/…, подробнее о лингвистическом корпусе здесь: blogs.msdn.com/b/michkap/archive/2004/12/11/279942.aspx

Simon Mourier 23.03.2013 12:00

@Quartermeister - и, кстати, я считаю, что .NET 2 и .NET4 ведут себя по-разному, поскольку .NET 4 всегда использует NORM_LINGUISTIC_CASING, а .NET 2 - нет (эти флаги появились в Windows Vista).

Simon Mourier 23.03.2013 12:13

Следует ли переместить метод с CompareOptions.IgnoreCase первым, потому что .ToLower явно неэффективен?

Michael Freidgeim 22.05.2013 14:37

В том же духе я бы рекомендовал добавить CompareOptions.IgnoreKanaType и CompareOptions.IgnoreWidth.

Casey 29.04.2014 18:56

Почему вы не написали «ddddfg» .IndexOf («Df», StringComparison.OrdinalIgnoreCase)?

Chen 23.08.2015 16:41

Я только что пробовал это. Я ищу 154 строковых шаблона в 40 000 файлов, игнорируя нижний регистр. Он очень медленный и работал часами. Использование Regex или ToLower может быть более подвержено ошибкам при поиске не на английском языке, но они оба намного быстрее.

James 01.03.2017 19:41

должно быть> -1 нет? Возможно, найденный индекс будет иметь индекс 0, и это не удастся. IndexOf возвращает -1, если не найден в строке.

Ryan Mann 24.05.2018 22:54

Совет: вместо использования текущего языка и региональных параметров для значения cultureInfo можно также использовать CultureInfo.InvariantCulture.

AFract 12.02.2019 19:31

SIK и sik. Большая разница.

Bedir 24.09.2019 20:52

строка title = "строка"; строка tobeCompared = "СТРОКА"; if (title.ToUpper (). Contains (tobeCompared.ToUpper ())) {// Напишите здесь свою логику} else {// Напишите здесь свою логику}

Bimal 21.11.2019 09:17

Использование RegEx - простой способ сделать это:

Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);

Ваш ответ точно такой же, как у guptat59, но, как было указано в его ответе, это будет соответствовать регулярному выражению, поэтому, если строка, которую вы тестируете, содержит какие-либо специальные символы регулярного выражения, она не даст желаемого результата.

Casey 10.12.2013 02:55

Это прямая копия этот ответ и страдает теми же проблемами, что отмечены в этом ответе

Liam 10.10.2016 13:04

Согласовано. Изучите регулярные выражения

Jared 26.12.2017 08:14

Метод InStr из сборки VisualBasic лучше всего подходит, если вас беспокоит интернационализация (или вы могли бы реализовать его заново). Глядя на него, dotNeetPeek показывает, что он учитывает не только заглавные и строчные буквы, но и тип кана, а также символы полной и половинной ширины (в основном актуально для азиатских языков, хотя есть и полноширинные версии латинского алфавита. ). Я пропускаю некоторые детали, но обратите внимание на частный метод InternalInStrText:

private static int InternalInStrText(int lStartPos, string sSrc, string sFind)
{
  int num = sSrc == null ? 0 : sSrc.Length;
  if (lStartPos > num || num == 0)
    return -1;
  if (sFind == null || sFind.Length == 0)
    return lStartPos;
  else
    return Utils.GetCultureInfo().CompareInfo.IndexOf(sSrc, sFind, lStartPos, CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth);
}

OrdinalIgnoreCase, CurrentCultureIgnoreCase или InvariantCultureIgnoreCase?

Поскольку этого нет, вот несколько рекомендаций о том, когда какой из них использовать:

Dos

  • Используйте StringComparison.OrdinalIgnoreCase для сравнения в качестве безопасного значения по умолчанию для сопоставления строк, не зависящего от языка и региональных параметров.
  • Использовать сравнения StringComparison.OrdinalIgnoreCase для увеличения скорости.
  • Используйте строковые операции StringComparison.CurrentCulture-based при отображении вывода пользователю.
  • Переключить текущее использование строковых операций на основе инварианта культура для использования нелингвистических StringComparison.Ordinal или StringComparison.OrdinalIgnoreCase при сравнении
    лингвистически нерелевантный (например, символический).
  • Используйте ToUpperInvariant, а не ToLowerInvariant, когда нормализующие строки для сравнения.

Не делать

  • Используйте перегрузки для строковых операций, которые явно не или неявно указать механизм сравнения строк.
  • Использовать строку на основе StringComparison.InvariantCulture
    операции в большинстве случаев; одним из немногих исключений будет
    сохраняющиеся лингвистически значимые, но культурно-независимые данные.

Исходя из этих правил, вы должны использовать:

string title = "STRING";
if (title.IndexOf("string", 0, StringComparison.[YourDecision]) != -1)
{
    // The string exists in the original
}

тогда как [YourDecision] зависит от рекомендаций сверху.

ссылка на источник: http://msdn.microsoft.com/en-us/library/ms973919.aspx

что, если вы знаете, что всегда получите английскую строку. какой использовать?

BKSpurgeon 24.03.2017 02:43

@BKSpurgeon Я бы использовал OrdinalIgnoreCase, если случай не имеет значения

Fabian Bigler 24.03.2017 11:09

Именно так:

string s = "AbcdEf";
if (s.ToLower().Contains("def"))
{
    Console.WriteLine("yes");
}

Это не зависит от культуры и в некоторых случаях может не работать. Необходимо использовать культуру.CompareInfo.IndexOf (абзац, слово, CompareOptions.IgnoreCase).

hikalkan 22.07.2014 11:50
Зачем избегать string.ToLower () при сравнении строк без учета регистра? Tl; Д-р Это дорого, потому что новая струна «изготавливается».
Liam 10.10.2016 13:00

Это очень похоже на другой пример здесь, но я решил упростить enum до bool, primary, потому что другие альтернативы обычно не нужны. Вот мой пример:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, bool bCaseInsensitive )
    {
        return source.IndexOf(toCheck, bCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) >= 0;
    }
}

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

if ( "main String substring".Contains("SUBSTRING", true) )
....

Уловка здесь заключается в том, чтобы искать строку, игнорируя регистр, но оставляя ее точно такой же (с тем же регистром).

 var s = "Factory Reset";
 var txt = "reset";
 int first = s.IndexOf(txt, StringComparison.InvariantCultureIgnoreCase) + txt.Length;
 var subString = s.Substring(first - txt.Length, txt.Length);

Выход "Сброс"

if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}

Вы можете использовать функцию string.indexof (). Это будет нечувствительно к регистру

Простой способ для новичка:

title.ToLower().Contains("string");//of course "string" is lowercase.

Проголосовать против просто за неправильность. Что если title = StRiNg? StRiNg! = Строка и StRiNg! = STRING

bernieslearnings 21.10.2017 07:30

Я ошибался. Отредактируйте ответ следующим образом, слишком просто: <br/> title.ToLower (). Contains ("string") // конечно, "string" в нижнем регистре

O Thạnh Ldt 23.03.2018 06:28
public static class StringExtension
{
    #region Public Methods

    public static bool ExContains(this string fullText, string value)
    {
        return ExIndexOf(fullText, value) > -1;
    }

    public static bool ExEquals(this string text, string textToCompare)
    {
        return text.Equals(textToCompare, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExHasAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index]) == false) return false;
        return true;
    }

    public static bool ExHasEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return true;
        return false;
    }

    public static bool ExHasNoEquals(this string text, params string[] textArgs)
    {
        return ExHasEquals(text, textArgs) == false;
    }

    public static bool ExHasNotAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return false;
        return true;
    }

    /// <summary>
    /// Reports the zero-based index of the first occurrence of the specified string
    /// in the current System.String object using StringComparison.InvariantCultureIgnoreCase.
    /// A parameter specifies the type of search to use for the specified string.
    /// </summary>
    /// <param name = "fullText">
    /// The string to search inside.
    /// </param>
    /// <param name = "value">
    /// The string to seek.
    /// </param>
    /// <returns>
    /// The index position of the value parameter if that string is found, or -1 if it
    /// is not. If value is System.String.Empty, the return value is 0.
    /// </returns>
    /// <exception cref = "ArgumentNullException">
    /// fullText or value is null.
    /// </exception>
    public static int ExIndexOf(this string fullText, string value)
    {
        return fullText.IndexOf(value, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExNotEquals(this string text, string textToCompare)
    {
        return ExEquals(text, textToCompare) == false;
    }

    #endregion Public Methods
}

если вы хотите проверить, находится ли ваша переданная строка в строке, для этого есть простой метод.

string yourStringForCheck= "abc";
string stringInWhichWeCheck= "Test abc abc";

bool isContained = stringInWhichWeCheck.ToLower().IndexOf(yourStringForCheck.ToLower()) > -1;

Это логическое значение вернется, если строка содержится или нет

Это самые простые решения.

  1. По индексу

    string title = "STRING";
    
    if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
    {
        // contains 
    }
    
  2. Изменяя регистр

    string title = "STRING";
    
    bool contains = title.ToLower().Contains("string")
    
  3. По Regex

    Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
    

Только .NET Core 2.0+ (на данный момент)

В .NET Core начиная с версии 2.0 есть пара методов, позволяющих справиться с этим:

  • String.Contains (Char, StringComparison)
  • String.Contains (Строка, StringComparison)

Пример:

"Test".Contains("test", System.StringComparison.CurrentCultureIgnoreCase);

Со временем они, вероятно, войдут в стандарт .NET, а оттуда во все другие реализации библиотеки базовых классов.

Теперь также доступно в .NET Standard 2.1

Paweł Bulwan 05.04.2020 14:32

Также доступно в .NET 5.0.

Dariusz Woźniak 17.11.2020 15:20

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

    public static bool ContainsIgnoreCase(this string paragraph, string word)
    {
        return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
    }

Предполагая, что ваш абзац и слово всегда будут на английском языке

Boris Callens 15.02.2019 16:42

Чтобы избежать проблем с принудительным переводом языка и региональных параметров в en-US, используйте вместо этого return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;.

AndrewWhalan 14.06.2019 00:42

Как просто так и работает

title.ToLower().Contains("String".ToLower())

Аналогично предыдущим ответам (с использованием метода расширения), но с двумя простыми нулевыми проверками (C# 6.0 и выше):

public static bool ContainsIgnoreCase(this string source, string substring)
{
    return source?.IndexOf(substring ?? "", StringComparison.OrdinalIgnoreCase) >= 0;
}

Если источник равен нулю, вернуть ложь (через оператор распространения нуля?.)

Если подстрока равна нулю, рассматривать ее как пустую строку и возвращать истину (с помощью оператора объединения с нулем ??)

StringComparison, конечно, может быть отправлен в качестве параметра при необходимости.

Основываясь на существующих ответах и ​​документации метода Contains, я бы рекомендовал создать следующее расширение, которое также позаботится о угловых случаях:

public static class VStringExtensions 
{
    public static bool Contains(this string source, string toCheck, StringComparison comp) 
    {
        if (toCheck == null) 
        {
            throw new ArgumentNullException(nameof(toCheck));
        }

        if (source.Equals(string.Empty)) 
        {
            return false;
        }

        if (toCheck.Equals(string.Empty)) 
        {
            return true;
        }

        return source.IndexOf(toCheck, comp) >= 0;
    }
}

Вы можете использовать параметр сравнения строк (доступен в .net 2.1 и выше) String.Contains - метод.

public bool Contains (string value, StringComparison comparisonType);

Пример:

string title = "ASTRINGTOTEST";
title.Contains("string", StringComparison.InvariantCultureIgnoreCase);

да, он доступен в .net Standard 2.1 и .Net Core 5.0 docs.microsoft.com/en-us/dotnet/api/… Исправлено как часть - github.com/dotnet/runtime/issues/22198

Surender Singh Malik 19.01.2021 15:40

Другие вопросы по теме