Выполнение строковых операций без учета языка и региональных параметров в коллекциях
В пространстве имен System.Collections существуют классы и члены, поведение которых по умолчанию зависит от языка и региональных параметров. Конструкторы без параметров для классов CaseInsensitiveComparer и CaseInsensitiveHashCodeProvider инициализируют новый экземпляр с помощью свойства Thread.CurrentCulture. Все перегрузки метода CollectionsUtil.CreateCaseInsensitiveHashtable создают новый экземпляр класса Hashtable, по умолчанию используя свойство Thread.CurrentCulture
. Перегруженные версии метода ArrayList.Sort по умолчанию выполняют сортировку с учетом языка и региональных параметров, используя свойства Thread.CurrentCulture
. Если в качестве ключей используются строки, на сортировку и поиск по SortedList влияет значение Thread.CurrentCulture
. Для получения результатов, не зависящих от языка и региональных параметров, для этих классов и методов в пространстве имен Collections
следуйте рекомендациям, приведенным в этом разделе.
Примечание.
Если передать CultureInfo.InvariantCulture в метод сравнения, сравнение выполняется без учета языка и региональных параметров. Однако при этом не выполняется нелингвистическое сравнение, например для путей к файлам, разделов реестра и переменных среды. Также не поддерживается принятие решений по безопасности на основе результата сравнения. Для нелингвистического сравнения и (или) поддержки принятия решений по безопасности в приложении следует использовать метод сравнения, который принимает значение StringComparison. Приложение должно передавать StringComparison.
Использование классов CaseInsensitiveComparer
и CaseInsensitiveHashCodeProvider
В конструкторах без параметров для CaseInsensitiveHashCodeProvider
и CaseInsensitiveComparer
инициализируется новый экземпляр класса с использованием Thread.CurrentCulture
. Это приводит к тому, что язык и региональные параметры учитываются при сравнении. В следующем примере кода показан конструктор для Hashtable
, который учитывает язык и региональные параметры, так как он использует конструкторы без параметров для CaseInsensitiveHashCodeProvider
и CaseInsensitiveComparer
.
internalHashtable = New Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default)
internalHashtable = new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
Если вы хотите создать Hashtable
, не учитывающий язык и региональные параметры, с помощью классов CaseInsensitiveComparer
и CaseInsensitiveHashCodeProvider
, инициализируйте новые экземпляры этих классов с помощью конструкторов, которые принимают параметр culture
. В качестве параметра culture
укажите CultureInfo.InvariantCulture. В следующем примере кода показан конструктор для Hashtable
, который не учитывает язык и региональные параметры.
internalHashtable = New Hashtable(New
CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture),
New CaseInsensitiveComparer(CultureInfo.InvariantCulture))
internalHashtable = new Hashtable(new CaseInsensitiveHashCodeProvider
(CultureInfo.InvariantCulture),
new CaseInsensitiveComparer(CultureInfo.InvariantCulture));
Использование метода CollectionsUtil.CreateCaseInsensitiveHashTable
Для создания нового экземпляра класса Hashtable
, который не учитывает регистр строк, удобно использовать метод CollectionsUtil.CreateCaseInsensitiveHashTable
. Однако все перегруженные версии метода CollectionsUtil.CreateCaseInsensitiveHashTable
учитывают язык и региональные параметры, так как они используют свойство Thread.CurrentCulture
. С помощью этого метода нельзя создать Hashtable
, который не учитывает язык и региональные параметры. Чтобы создать Hashtable
, который не учитывает язык и региональные параметры, используйте конструктор Hashtable
, который принимает параметр culture
. В качестве параметра culture
укажите CultureInfo.InvariantCulture
. В следующем примере кода показан конструктор для Hashtable
, который не учитывает язык и региональные параметры.
internalHashtable = New Hashtable(New
CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture),
New CaseInsensitiveComparer(CultureInfo.InvariantCulture))
internalHashtable = new Hashtable(new CaseInsensitiveHashCodeProvider
(CultureInfo.InvariantCulture),
new CaseInsensitiveComparer(CultureInfo.InvariantCulture));
Использование класса SortedList
SortedList
представляет коллекцию пар "ключ — значение", упорядоченных по ключу. Обращаться к парам можно по ключу и индексу. Если используется SortedList
и в качестве ключей используются строки, на поиск и сортировку может повлиять свойство Thread.CurrentCulture
. Чтобы SortedList
не учитывал язык и региональные параметры, создайте SortedList
с помощью одного из конструкторов, принимающих параметр comparer
. Параметр comparer
указывает реализацию IComparer, которую нужно использовать при сравнении ключей. Для сравнения ключей в качестве параметра укажите пользовательский класс сравнения, который использует CultureInfo.InvariantCulture
. В следующем примере показан пользовательский класс сравнения, не учитывающий язык и региональные параметры. Для этого в конструктор SortedList
передается параметр comparer
.
Imports System.Collections
Imports System.Globalization
Friend Class InvariantComparer
Implements IComparer
Private m_compareInfo As CompareInfo
Friend Shared [Default] As New InvariantComparer()
Friend Sub New()
m_compareInfo = CultureInfo.InvariantCulture.CompareInfo
End Sub
Public Function Compare(a As Object, b As Object) As Integer _
Implements IComparer.Compare
Dim sa As String = CType(a, String)
Dim sb As String = CType(b, String)
If Not (sa Is Nothing) And Not (sb Is Nothing) Then
Return m_compareInfo.Compare(sa, sb)
Else
Return Comparer.Default.Compare(a, b)
End If
End Function
End Class
using System;
using System.Collections;
using System.Globalization;
internal class InvariantComparer : IComparer
{
private CompareInfo _compareInfo;
internal static readonly InvariantComparer Default = new
InvariantComparer();
internal InvariantComparer()
{
_compareInfo = CultureInfo.InvariantCulture.CompareInfo;
}
public int Compare(Object a, Object b)
{
if (a is string sa && b is string sb)
return _compareInfo.Compare(sa, sb);
else
return Comparer.Default.Compare(a,b);
}
}
В общем случае при использовании SortedList
для строк без указания пользовательского инвариантного класса сравнения изменение Thread.CurrentCulture
после заполнения списка может сделать список недействительным.
Использование метода ArrayList.Sort
Перегруженные версии метода по умолчанию ArrayList.Sort
выполняют сортировку с учетом языка и региональных параметров благодаря использованию свойства Thread.CurrentCulture
. Результаты могут различаться из-за различного порядка сортировки в разных языках и региональных параметрах. Чтобы результат не зависел от языка и региональных параметров, используйте перегрузки этого метода, которые принимают реализацию IComparer
. В качестве параметра comparer
укажите пользовательский инвариантный класс сравнения, который использует CultureInfo.InvariantCulture
. Пример пользовательского инвариантного класса сравнения приведен в разделе Использование класса SortedList.