← Назад к вопросам

Как сравниваются строки?

1.3 Junior🔥 101 комментариев
#Основы C# и .NET

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сравнение строк в C#

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

Основные методы и операторы сравнения

1. Операторы == и !=

Эти операторы переопределены в классе string для сравнения значений, а не ссылок.

string str1 = "Hello";
string str2 = "Hello";
string str3 = new string("Hello".ToCharArray());

Console.WriteLine(str1 == str2); // True (одинаковое значение)
Console.WriteLine(str1 == str3); // True (одинаковое значение, несмотря на разные объекты)
Console.WriteLine(object.ReferenceEquals(str1, str3)); // False (разные объекты в памяти)

2. Метод Equals

Имеет несколько перегрузок для сравнения значений строк.

string a = "Test";
string b = "test";

// Сравнение с учетом регистра (по умолчанию)
bool defaultEquals = a.Equals(b); // False
// Сравнение без учета регистра
bool ignoreCase = a.Equals(b, StringComparison.OrdinalIgnoreCase); // True

3. String.Compare и String.CompareTo

Эти методы возвращают целое число, указывающее лексикографическое отношение между строками.

int result1 = string.Compare("apple", "banana"); // -1 (apple < banana)
int result2 = string.Compare("Apple", "apple", StringComparison.OrdinalIgnoreCase); // 0 (равны при игнорировании регистра)
int result3 = "cherry".CompareTo("cherry"); // 0 (равны)

Ключевые аспекты сравнения строк

Учет культурных особенностей (Culture-aware comparison)

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

string strA = "straße";
string strB = "strasse";

// Сравнение с учетом немецкой культуры
bool cultureEquals = string.Equals(strA, strB, StringComparison.CurrentCulture); // Может быть True в de-DE
// Инвариантное сравнение
bool invariantEquals = string.Equals(strA, strB, 
    StringComparison.InvariantCulture); // False

Порядковое сравнение (Ordinal comparison)

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

// Порядковое сравнение (по кодам символов)
bool ordinalEquals = string.Equals("Hello", "HELLO", 
    StringComparison.Ordinal); // False
bool ordinalIgnoreCase = string.Equals("Hello", "HELLO", 
    StringComparison.OrdinalIgnoreCase); // True

Инвариантное сравнение (Invariant culture)

Использует инвариантную культуру (CultureInfo.InvariantCulture), которая не зависит от конкретного языка/региона. Полезно для системных операций, где нужна согласованность.

Рекомендации по использованию разных типов сравнения

Тип сравненияКогда использоватьПример
OrdinalВнутренние идентификаторы, пути файлов, XML/JSON тегиStringComparison.Ordinal
OrdinalIgnoreCaseИмена файлов в Windows, URL-адресаStringComparison.OrdinalIgnoreCase
CurrentCultureОтображение данных пользователю, сортировкаStringComparison.CurrentCulture
InvariantCultureСохранение данных, системные форматыStringComparison.InvariantCulture
// Практический пример: выбор типа сравнения
public bool ValidateUsername(string username, string existingUsername)
{
    // Для имени пользователя используем порядковое сравнение
    return string.Equals(username, existingUsername, 
        StringComparison.OrdinalIgnoreCase);
}

public bool ValidateDisplayName(string name1, string name2)
{
    // Для отображаемых имен учитываем культурные особенности
    return string.Equals(name1, name2, 
        StringComparison.CurrentCulture);
}

Важные нюансы и оптимизация

  1. Интернирование строк: C# автоматически интернирует строковые литералы, что может влиять на сравнение ссылок.
string s1 = "Hello";
string s2 = "Hello";
string s3 = string.Intern(new StringBuilder().Append("He").Append("llo").ToString());

Console.WriteLine(object.ReferenceEquals(s1, s2)); // True
Console.WriteLine(object.ReferenceEquals(s1, s3)); // True (благодаря интернированию)
  1. Производительность: StringComparison.Ordinal обычно быстрее других методов, так как не учитывает культурные правила.

  2. Безопасность: Для сравнения паролей, ключей безопасности всегда используйте порядковое сравнение с учетом времени выполнения (time-constant comparison) через специализированные методы криптографии.

  3. Null-безопасность: Методы сравнения обычно обрабатывают null значения:

string nullStr = null;
Console.WriteLine(string.Equals(nullStr, "test")); // False
Console.WriteLine("test".Equals(nullStr)); // False
// Console.WriteLine(nullStr.Equals("test")); // NullReferenceException!

Лучшие практики

  • Всегда явно указывайте StringComparison параметр в перегрузках методов для избежания неявного поведения
  • Для внутренних служебных строк используйте StringComparison.Ordinal или StringComparison.OrdinalIgnoreCase
  • Для строк, отображаемых пользователю, используйте StringComparison.CurrentCulture
  • Избегайте сравнения строк с помощью ToUpper()/ToLower() без параметров культуры

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