.net - Проблемы с Array.Sort и Array.BinarySearch - культура и глобализация - PullRequest
1 голос
/ 20 апреля 2009

Мне нужно отсортировать массив, содержащий список слов, и искать его с помощью binarysearch. По определенным причинам список слов всегда должен быть отсортирован с использованием правил сортировки «en-US», т.е. американских региональных настроек. Код будет работать в различных международных операционных системах, и, конечно, это будет означать, что список слов будет отсортирован по-разному в соответствии с используемыми локальными региональными настройками. Одна проблема может возникнуть на компьютере / устройстве, работающем с региональными настройками Литвы. Зачем? Поскольку буква " Y " на большинстве языков сортируется как X- Y -Z, а на литовском, порядок сортировки - I- Y -J. Такое поведение может привести к хаосу в моей программе.

На настольном ПК я мог на мгновение изменить региональные настройки на американский английский, используя:

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture ("en-US")

однако, поскольку я занимаюсь разработкой для Windows Mobile (CF.NET), этот фрагмент кода невозможно реализовать.

Я нашел несколько хаков, которые позволили бы мне программно изменить региональные настройки на устройстве, но они не являются «официальными» и считаются рискованными, поэтому я предпочитаю избегать их.

Поэтому мой вопрос: как заставить Array.Sort и Array.BinarySearch использовать CultureInfo = "en-US" при сортировке и поиске независимо от региональных настроек, установленных на устройстве?

Полагаю, я мог бы использовать:

Public Shared Function BinarySearch(Of T) ( _
    array As T(), _
    value As T, _
    comparer As IComparer(Of T) _
) As Integer

и внедрить Comparer, чтобы учесть CultureInfo (и установить для него значение «en-US»), но я не знаю, как это сделать, несмотря на все усилия. Если бы кто-нибудь мог опубликовать пример кода в VB.Net или C # или объяснить, как это сделать, я был бы очень признателен.

Если вам известно о каком-либо альтернативном решении, которое работает в CF.Net, тогда, конечно, я весь в ушах.

Спасибо.

EDIT:

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

Однако из соображений гибкости я считаю, что ответ Гуффы - лучший. Зачем? Давайте рассмотрим другой пример: на немецком языке буква Ö сортируется ... -X-Z, а на шведском и финском языках порядок X-Z- ... 1037 *. На эстонском языке порядок сортировки: Z- ... 1039 * -X. Сложно, не правда ли? Решение Guffa позволит мне принудительно использовать шведский сортировочный код (изменяющий CultureInfo) на устройстве, работающем в региональных настройках Германии. Использование Comparer.DefaultInvariant с его связью с английским не помогло бы в этом случае, вероятно, буква ... закончилась бы с O. Поэтому мой голос переместится на Guffa.

Ответы [ 3 ]

6 голосов
/ 20 апреля 2009

Ну, ответ на оба вопроса заключается в реализации компаратора. Создайте класс, который реализует интерфейс IComprarer(Of String) и имеет собственный объект CultureInfo, который он использует для сравнения строк:

Public Class StringComparerEnUs
   Implements IComparer(Of String)

   Private _culture As CultureInfo

   Public Sub New()
      _culture = New CultureInfo("en-US")
   End Sub

   Public Function Compare(ByVal x As String, ByVal y As String)
      Return String.Compate(x, y, false, _culture)
   End Function

End Class

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

Array.Sort(theArray, New StringComparerEnUs())

и найти их:

pos = BinarySearch(theArray, "Dent, Arthur", new StringComparerEnUs())

(Конечно, класс можно сделать более общим, приняв строку культуры в конструкторе, и вы также можете добавить переменную, чтобы использовать параметр ignorecase в вызове String.Compare.)

5 голосов
/ 20 апреля 2009

Разве нельзя использовать культуру Инвариант ?

InvariantCulture извлекает экземпляр инвариантной культуры. это связано с английским языком но не с какой-либо страной / регионом.

Использование инвариантной культуры сделало бы это тривиальным.

Array.Sort( myArray, Comparer.DefaultInvariant );

Array.BinarySearch( myArray, myString, Comparer.DefaultInvariant );
1 голос
/ 20 апреля 2009

Попробуйте это:

class EnglishComparer : IComparer<string>
{
  static CultureInfo __english = new CultureInfo("en-US");

  public int Compare(string x, string y)
  {
    return string.Compare(x, y, __english, CompareOptions.None);
  }
}
...