Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Вы сравниваете строки, чтобы ответить на один из двух вопросов: "Равны ли эти две строки?" или "В каком порядке эти строки должны быть размещены при их сортировке?"
Следующие факторы усложняют эти два вопроса:
- Вы можете выбрать порядковое или лингвистическое сравнение.
- Вы можете выбрать, имеет ли дело дело.
- Вы можете выбрать сравнения, специфичные для культуры.
- Лингвистические сравнения зависят от культуры и платформы.
Поля System.StringComparison перечисления представляют следующие варианты:
- CurrentCulture: сравнение строк с использованием правил сортировки с учетом языка и региональных параметров.
- CurrentCultureIgnoreCase: сравнивайте строки, используя правила сортировки, учитывающие текущую культуру, и игнорируя регистр сравниваемых строк.
- InvariantCulture: сравнение строк с учетом правил сортировки для инвариантной культуры.
- InvariantCultureIgnoreCase: сравнивайте строки с использованием правил сортировки, учитывающих культуру и инвариантную культуру, при этом игнорируя регистр строк.
- Ordinal: Сравнивайте строки, используя ординальные (двоичные) правила сортировки.
- OrdinalIgnoreCase: сравнение строк с использованием порядковых (двоичных) правил сортировки с игнорированием регистра сравниваемых строк.
При сравнении строк определяется порядок между ними. Сравнения используются для сортировки последовательности строк. Когда последовательность упорядочена в известном порядке, искать проще как программам, так и людям. Другие сравнения могут проверить, совпадают ли строки. Эти проверки сходства похожи на равенство, но некоторые различия, такие как различия в случае, могут быть проигнорированы.
Сравнение порядковых чисел по умолчанию
По умолчанию наиболее распространенные операции:
- String.Equals
-
String.Equality и String.Inequality, то есть операторы
==равенства и!=соответственно выполняют регистрозависимое и порядковое сравнение. String.Equals имеет перегрузку, в которой аргумент StringComparison можно предоставить для изменения правил сортировки. Это показано в следующем примере:
string root = @"C:\users";
string root2 = @"C:\Users";
bool result = root.Equals(root2);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");
result = root.Equals(root2, StringComparison.Ordinal);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");
Console.WriteLine($"Using == says that <{root}> and <{root2}> are {(root == root2 ? "equal" : "not equal")}");
Сравнение строк по умолчанию с использованием порядкового метода не учитывает лингвистические правила. Он сравнивает двоичное значение каждого Char объекта в двух строках. В результате стандартное порядковое сравнение также учитывает регистр.
Тест на равенство с String.Equals и == и != операторы отличается от сравнения строк с помощью String.CompareTo и Compare(String, String) методами. Все они выполняют сравнение с учетом регистра. Однако, хотя тесты на равенство выполняют порядковое сравнение, методы CompareTo и Compare выполняют языковое сравнение с учетом текущих культурных и языковых параметров. Очистите намерение кода, вызвав перегрузку, которая явно указывает тип сравнения для выполнения.
Вы можете использовать оператор is и константный шаблон в качестве альтернативы ==, когда правый операнд является константой.
Сравнение порядковых значений без учета регистра
Этот String.Equals(String, StringComparison) метод позволяет указать StringComparison значение StringComparison.OrdinalIgnoreCase для нечувствительного к регистру порядкового сравнения. Существует также статический String.Compare(String, String, StringComparison) метод, который выполняет порядковое сравнение, нечувствительное к регистру, если указать значение StringComparison.OrdinalIgnoreCase в качестве аргумента StringComparison. Эти сравнения показаны в следующем коде:
string root = @"C:\users";
string root2 = @"C:\Users";
bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
bool areEqual = String.Equals(root, root2, StringComparison.OrdinalIgnoreCase);
int comparison = String.Compare(root, root2, comparisonType: StringComparison.OrdinalIgnoreCase);
Console.WriteLine($"Ordinal ignore case: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");
Console.WriteLine($"Ordinal static ignore case: <{root}> and <{root2}> are {(areEqual ? "equal." : "not equal.")}");
if (comparison < 0)
{
Console.WriteLine($"<{root}> is less than <{root2}>");
}
else if (comparison > 0)
{
Console.WriteLine($"<{root}> is greater than <{root2}>");
}
else
{
Console.WriteLine($"<{root}> and <{root2}> are equivalent in order");
}
Эти методы используют соглашения о регистре инвариантного языка и региональных параметров при выполнении нечувствительного порядкового сравнения регистра.
Лингвистические сравнения
Многие методы сравнения строк (например String.StartsWith) используют лингвистические правила для текущей культуры по умолчанию для упорядочивания входных данных. Это лингвистическое сравнение иногда называется "порядком сортировки слов". При выполнении лингвистического сравнения некоторые неэлементные символы Юникода могут иметь специальные весовые значения. Например, дефис "-" может иметь небольшой вес, назначенный ему, чтобы "co-op" и "coop" отображались рядом друг с другом в порядке сортировки. Некоторые непечатные символы элемента управления могут игнорироваться. Кроме того, некоторые символы Юникода могут быть эквивалентны последовательности экземпляров Char . В следующем примере используется фраза "Они танцуют на улице" в немецком языке с "ss" (U+0073 U+0073) в одной строке и "ß" (U+00DF) в другой строке. Лингвистически (в Windows) "ss" равно немецкому символу эсцет: "ß" в культурах "en-US" и "de-DE".
string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";
Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");
bool equal = String.Equals(first, second, StringComparison.InvariantCulture);
Console.WriteLine($"The two strings {(equal == true ? "are" : "are not")} equal.");
showComparison(first, second);
string word = "coop";
string words = "co-op";
string other = "cop";
showComparison(word, words);
showComparison(word, other);
showComparison(words, other);
void showComparison(string one, string two)
{
int compareLinguistic = String.Compare(one, two, StringComparison.InvariantCulture);
int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
if (compareLinguistic < 0)
{
Console.WriteLine($"<{one}> is less than <{two}> using invariant culture");
}
else if (compareLinguistic > 0)
{
Console.WriteLine($"<{one}> is greater than <{two}> using invariant culture");
}
else
{
Console.WriteLine($"<{one}> and <{two}> are equivalent in order using invariant culture");
}
if (compareOrdinal < 0)
{
Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
}
else if (compareOrdinal > 0)
{
Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
}
else
{
Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}
}
В Windows до .NET 5 порядок сортировки "cop", "coop" и "co-op" изменяется при изменении лингвистического сравнения на порядковое сравнение. Два немецких предложения также сравниваются по-разному с использованием различных типов сравнения. До .NET 5 API глобализации .NET использовали библиотеки национальной поддержки языка (NLS). В .NET 5 и более поздних версиях API глобализации .NET используют библиотеки International Components for Unicode (ICU), которые унифицируют поведение глобализации .NET во всех поддерживаемых операционных системах.
Сравнения с использованием определенных культур
В следующем примере хранятся объекты CultureInfo для культур en-US и de-DE. Сравнения выполняются с помощью объекта CultureInfo, чтобы обеспечить культурно-специфическое сравнение. Используемая культура влияет на лингвистические сравнения. В следующем примере показаны результаты сравнения двух немецких предложений, используя культуру "en-US" и культуру "de-DE".
string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";
Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");
var en = new System.Globalization.CultureInfo("en-US");
// For culture-sensitive comparisons, use the String.Compare
// overload that takes a StringComparison value.
int i = String.Compare(first, second, en, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {en.Name} returns {i}.");
var de = new System.Globalization.CultureInfo("de-DE");
i = String.Compare(first, second, de, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {de.Name} returns {i}.");
bool b = String.Equals(first, second, StringComparison.CurrentCulture);
Console.WriteLine($"The two strings {(b ? "are" : "are not")} equal.");
string word = "coop";
string words = "co-op";
string other = "cop";
showComparison(word, words, en);
showComparison(word, other, en);
showComparison(words, other, en);
void showComparison(string one, string two, System.Globalization.CultureInfo culture)
{
int compareLinguistic = String.Compare(one, two, en, System.Globalization.CompareOptions.None);
int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
if (compareLinguistic < 0)
{
Console.WriteLine($"<{one}> is less than <{two}> using en-US culture");
}
else if (compareLinguistic > 0)
{
Console.WriteLine($"<{one}> is greater than <{two}> using en-US culture");
}
else
{
Console.WriteLine($"<{one}> and <{two}> are equivalent in order using en-US culture");
}
if (compareOrdinal < 0)
{
Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
}
else if (compareOrdinal > 0)
{
Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
}
else
{
Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}
}
Сравнения с учетом языка и региональных параметров обычно используются для сравнения и сортировки входных строк пользователями с другими строками. Символы и соглашения сортировки этих строк могут отличаться в зависимости от региональных настроек компьютера пользователя. Даже строки, содержащие идентичные символы, могут упорядочиваться по-разному в зависимости от культуры текущего потока.
Лингвистическая сортировка и поиск строк в массивах
В следующих примерах показано, как сортировать и искать строки в массиве с помощью лингвистического сравнения, зависящего от текущего языка и региональных параметров. Вы используете статические Array методы, которые принимают System.StringComparer параметр.
В следующем примере показано, как сортировать массив строк, используя текущие региональные параметры.
string[] lines =
[
@"c:\public\textfile.txt",
@"c:\public\textFile.TXT",
@"c:\public\Text.txt",
@"c:\public\testfile2.txt"
];
Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
Console.WriteLine($" {s}");
}
Console.WriteLine("\n\rSorted order:");
// Specify Ordinal to demonstrate the different behavior.
Array.Sort(lines, StringComparer.CurrentCulture);
foreach (string s in lines)
{
Console.WriteLine($" {s}");
}
После сортировки массива можно найти записи с помощью двоичного поиска. Двоичный поиск начинается в середине коллекции, чтобы определить, какая половина коллекции будет содержать запрошенную строку. Каждое последующее сравнение подразделяет оставшуюся часть коллекции в половину. Массив сортируется с помощью StringComparer.CurrentCulture. Локальная функция ShowWhere отображает сведения о том, где найдена строка. Если строка не найдена, возвращаемое значение указывает, где он будет находиться, если бы он был найден.
string[] lines =
[
@"c:\public\textfile.txt",
@"c:\public\textFile.TXT",
@"c:\public\Text.txt",
@"c:\public\testfile2.txt"
];
Array.Sort(lines, StringComparer.CurrentCulture);
string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = Array.BinarySearch(lines, searchString, StringComparer.CurrentCulture);
ShowWhere<string>(lines, result);
Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");
void ShowWhere<T>(T[] array, int index)
{
if (index < 0)
{
index = ~index;
Console.Write("Not found. Sorts between: ");
if (index == 0)
{
Console.Write("beginning of sequence and ");
}
else
{
Console.Write($"{array[index - 1]} and ");
}
if (index == array.Length)
{
Console.WriteLine("end of sequence.");
}
else
{
Console.WriteLine($"{array[index]}.");
}
}
else
{
Console.WriteLine($"Found at index {index}.");
}
}
Порядковый порядок сортировки и поиска в коллекциях
Следующий код использует System.Collections.Generic.List<T> класс коллекции для хранения строк. Строки сортируются с помощью List<T>.Sort метода. Этот метод требует делегата, который сравнивает и упорядочивает две строки. Этот String.CompareTo метод предоставляет функцию сравнения. Запустите пример и наблюдайте за порядком. Эта операция сортировки использует порядковую сортировку с учетом регистра. Статические String.Compare методы используются для указания различных правил сравнения.
List<string> lines =
[
@"c:\public\textfile.txt",
@"c:\public\textFile.TXT",
@"c:\public\Text.txt",
@"c:\public\testfile2.txt"
];
Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
Console.WriteLine($" {s}");
}
Console.WriteLine("\n\rSorted order:");
lines.Sort((left, right) => left.CompareTo(right));
foreach (string s in lines)
{
Console.WriteLine($" {s}");
}
После сортировки список строк можно искать с помощью двоичного поиска. В следующем примере показано, как искать отсортированный список с помощью той же функции сравнения. Локальная функция ShowWhere показывает, где находится искомый текст:
List<string> lines =
[
@"c:\public\textfile.txt",
@"c:\public\textFile.TXT",
@"c:\public\Text.txt",
@"c:\public\testfile2.txt"
];
lines.Sort((left, right) => left.CompareTo(right));
string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = lines.BinarySearch(searchString);
ShowWhere<string>(lines, result);
Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");
void ShowWhere<T>(IList<T> collection, int index)
{
if (index < 0)
{
index = ~index;
Console.Write("Not found. Sorts between: ");
if (index == 0)
{
Console.Write("beginning of sequence and ");
}
else
{
Console.Write($"{collection[index - 1]} and ");
}
if (index == collection.Count)
{
Console.WriteLine("end of sequence.");
}
else
{
Console.WriteLine($"{collection[index]}.");
}
}
else
{
Console.WriteLine($"Found at index {index}.");
}
}
Всегда следует использовать один и тот же тип сравнения для сортировки и поиска. Использование различных типов сравнения для сортировки и поиска приводит к непредвиденным результатам.
Классы коллекций, такие как System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey,TValue> и System.Collections.Generic.List<T>, имеют конструкторы, которые принимают параметр System.StringComparer, когда тип элементов или ключей — string. Как правило, эти конструкторы следует использовать всякий раз, когда это возможно, и указывать либо StringComparer.Ordinal, либо StringComparer.OrdinalIgnoreCase.