针对特定区域性对数据进行比较和排序

更新:2007 年 11 月

用于对项排序的字母顺序和约定随区域性的不同而不同。例如,排序顺序可以是区分大小写的,也可以是不区分大小写的。它可以是基于发音的,也可以是基于字符外观的。在东亚语言中,按文字的笔画和部首进行排序。排序也可能随语言和区域性使用的字母表基本顺序的不同而不同。例如,瑞典语中有“Æ”字符,它在字母表中排在“Z”之后。德语中也有该字符,但它在字母表中同“ae”一样排在“A”之后。全球通用的应用程序必须能够针对每个区域性对数据进行比较和排序,以支持区域性特定和语言特定的排序约定。

注意   有些时候不需要区分区域性的行为。有关何时以及如何执行不区分区域性的操作的更多信息,请参见“不区分区域性的字符串操作”。

比较字符串

CompareInfo 类提供了一组方法,可用于执行区分区域性的字符串比较。CultureInfo 类具有 CompareInfo 属性,该属性是此类的一个实例。该属性定义如何针对特定区域性对字符串进行比较和排序。Compare() 方法使用 CompareInfo 属性中的信息来比较字符串。如果 string1 小于 string2,则 String.Compare 方法返回一个负整数;如果 string1 和 string2 相等,则返回零;如果 string1 大于 string2,则返回一个正整数。

下面的代码示例演示如何根据用于执行比较的区域性,通过 String.Compare 方法以不同的方式来计算两个字符串。首先,将 CurrentCulture 设置丹麦语(丹麦),并比较字符串“Apple”和“Æble”。丹麦语将字符“Æ”视为单个字母,并在字母表中将其排在“Z”之后。因此,对于丹麦语区域性,字符串“Æble”比“Apple”大。接下来,将 CurrentCulture 设置为英语(美国),并再次比较字符串“Apple”和“Æble”。这次,字符串“Æble”被确定为小于“Apple”。英语语言将字符“Æ”视为一个特殊符号,并在字母表中将其排在字母“A”之前。

Imports System
Imports System.Globalization
Imports System.Threading
Imports Microsoft.VisualBasic

Public Class TestClass
   Public Shared Sub Main()
      Dim str1 As String = "Apple"
      Dim str2 As String = "Æble"
      
      ' Sets the CurrentCulture to Danish in Denmark.
      Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
      Dim result1 As Integer = [String].Compare(str1, str2)
      Console.WriteLine(ControlChars.Newline + "When the CurrentCulture _
         is ""da-DK""," + ControlChars.Newline + " the result of _
         comparing_{0} with {1} is: {2}", str1, str2, result1)
      
      ' Sets the CurrentCulture to English in the U.S.
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      Dim result2 As Integer = [String].Compare(str1, str2)
      Console.WriteLine(ControlChars.Newline + "When the _
         CurrentCulture is""en-US""," + ControlChars.Newline + " _
         the result of comparing {0} with {1} is: {2}", str1, _
         str2,result2)
   End Sub
End Class
using System;
using System.Globalization;
using System.Threading;

public class CompareStringSample
{
   public static void Main()
   {
      string str1 = "Apple";
      string str2 = "Æble"; 

      // Sets the CurrentCulture to Danish in Denmark.
      Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
      // Compares the two strings.
      int result1 = String.Compare(str1, str2);
      Console.WriteLine("\nWhen the CurrentCulture is \"da-DK\",\nthe 
            result of comparing {0} with {1} is: {2}",str1, str2, 
            result1);

      // Sets the CurrentCulture to English in the U.S.
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      // Compares the two strings.
      int result2 = String.Compare(str1, str2);
      Console.WriteLine("\nWhen the CurrentCulture is \"en-US\",\nthe 
            result of comparing {0} with {1} is: {2}",str1, str2, 
            result2);
   }
}

如果执行这些代码,则输出结果为:

When the CurrentCulture is "da-DK", 
the result of comparing Apple with Æble is: -1

When the CurrentCulture is "en-US", 
the result of comparing Apple with Æble is: 1

有关比较字符串的更多信息,请参见比较字符串

使用替换排序顺序

某些区域性支持多种排序顺序。例如,区域性“zh-CN”(中文 - 中国)支持按发音排序(默认)和按笔画数排序。当应用程序使用区域性名称(如“zh-CN”)创建 CultureInfo 对象时,使用的是默认排序顺序。若要指定替换排序顺序,应用程序应使用替换排序顺序的 LCID 来创建 CultureInfo 对象。然后,应用程序应从 CompareInfo 获取 CompareInfo 对象,以便在字符串比较中使用。或者,应用程序可以使用 GetCompareInfo() 直接创建一个 CompareInfo 对象,指定替换排序顺序的区域设置标识符 (LCID)。

下表列出了支持替换排序顺序的区域性以及默认和替换排序顺序的 LCID。

区域性名称

Culture

默认排序名称和 LCID

替换排序名称和 LCID

es-ES

西班牙语(西班牙)

国际:0x00000C0A

传统:0x0000040A

zh-TW

中文(台湾)

笔画数:0x00000404

注音符号:0x00030404

zh-CN

中文(中国)

发音:0x00000804

笔画数:0x00020804

zh-HK

中文(香港特别行政区)

笔画数:0x00000c04

笔画数:0x00020c04

zh-SG

中文(新加坡)

发音:0x00001004

笔画数:0x00021004

zh-MO

中文(澳门特别行政区)

发音:0x00001404

笔画数:0x00021404

ja-JP

日语(日本)

默认:0x00000411

Unicode:0x00010411

ko-KR

朝鲜语(韩国)

默认:0x00000412

朝鲜语 Xwansung - Unicode:0x00010412

de-DE

德语(德国)

词典:0x00000407

电话簿排序 DIN:0x00010407

hu-HU

匈牙利语(匈牙利)

默认:0x0000040e

技术排序:0x0001040e

ka-GE

格鲁吉亚语(格鲁吉亚)

传统:0x00000437

现代排序:0x00010437

搜索字符串

应用程序可以使用重载的 IndexOf() 方法在指定字符串中检索某个字符或子字符串的从零开始的索引。如果在指定字符串中未找到该字符或子字符串,此方法将检索到一个负整数。在使用 CompareInfo.IndexOf 搜索指定字符时,应用程序应考虑到,在执行比较的方式上,接受 CompareOptions 参数的方法重载与不接受此参数的方法重载是不同的。不接受 CompareOptions 参数的方法重载在搜索字符类型时,执行的是区分区域性的搜索。这就是说,如果一个 Unicode 值表示预先撰写的字符,如连字“Æ”(\u00C6),则根据区域性的不同,它可能被视为等效于它各部分以正确顺序排列的任何形式,如“AE”(\u0041\u0045)。若要执行顺序(不区分区域性)搜索(即,仅当 Unicode 值相同时,两个字符类型才视为相等),应用程序应使用接受 CompareOptions 参数的 CompareInfo.IndexOf 重载之一,并将该参数设置为 Ordinal 值。

应用程序也可以使用搜索字符的 IndexOf() 方法重载来执行序号(不区分区域性)搜索。请注意,搜索字符串的此方法重载执行的是区分区域性的搜索。

下面的代码示例演示在不同区域性下,IndexOf 方法的检索结果的差异。针对丹麦语(丹麦)创建 CultureInfo 对象,指定为“da-DK”。接下来,使用 CompareInfo.IndexOf 方法的重载在字符串“Æble”和“aeble”中搜索字符“Æ”。请注意,对于“da-DK”区域性,接受设置为 Ordinal 的 CompareOptions 参数的 CompareInfo.IndexOf 方法与不接受此参数的同一方法检索到的内容是一样的。字符“Æ”仅被视为等效于 Unicode 代码值 \u00E6。

Imports System
Imports System.Globalization
Imports System.Threading
Imports Microsoft.VisualBasic

Public Class CompareClass
   Public Shared Sub Main()
      Dim str1 As String = "Æble"
      Dim str2 As String = "aeble"
      Dim find As Char = "Æ"
      
      ' Creates a CultureInfo for Danish in Denmark.
      Dim ci As New CultureInfo("da-DK")
      
      Dim result1 As Integer = ci.CompareInfo.IndexOf(str1, find)
      Dim result2 As Integer = ci.CompareInfo.IndexOf(str2, find)
      Dim result3 As Integer = ci.CompareInfo.IndexOf(str1, find, _ 
         CompareOptions.Ordinal)
      Dim result4 As Integer = ci.CompareInfo.IndexOf(str2, find, _
         CompareOptions.Ordinal)      
      
      Console.WriteLine(ControlChars.Newline + "CultureInfo is set to _
         {0}", ci.DisplayName)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str1, result1)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str2, result2)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char, CompareOptions) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str1, result3)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char, CompareOptions) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str2, result4)
   End Sub
End Class
using System;
using System.Globalization;
using System.Threading;

public class CompareClass
{

   public static void Main()
   {
      string str1 = "Æble";
      string str2 = "aeble"; 
      char find = 'Æ';

      // Creates a CultureInfo for Danish in Denmark.
      CultureInfo ci= new CultureInfo("da-DK");

      int result1 = ci.CompareInfo.IndexOf(str1, find);
      int result2 = ci.CompareInfo.IndexOf(str2, find);
      int result3 = ci.CompareInfo.IndexOf(str1, find,   
         CompareOptions.Ordinal);
      int result4 = ci.CompareInfo.IndexOf(str2, find, 
         CompareOptions.Ordinal);

      Console.WriteLine("\nCultureInfo is set to {0} ", ci.DisplayName);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) 
         method\nthe result of searching for {0} in the string {1} is: 
         {2}", find, str1, result1);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) 
         method\nthe result of searching for {0} in the string {1} is: 
         {2}", find, str2, result2);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, 
         CompareOptions) method\nthe result of searching for {0} in the 
         string {1} is: {2}", find, str1, result3);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, 
         CompareOptions) method\nthe result of searching for {0} in the 
         string {1} is: {2}", find, str2, result4);
   }
}

此代码产生下列输出:

CultureInfo is set to Danish (Denmark) 

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string aeble is: -1

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string aeble is: -1

如果应用程序用 CultureInfo ci = new CultureInfo ("en-US") 替换 CultureInfo ci = new CultureInfo ("da-DK"),则带有设置为 Ordinal 的 CompareOptions 参数的 IndexOf() 方法与不带有此参数的同一方法将检索到不同结果。IndexOf 方法执行的区分区域性的比较认为字符“Æ”与其组成部分“ae”等效。IndexOf 方法执行的序号(不区分区域性)比较则不检索与“ae”等效的字符“Æ”,这是因为它们的 Unicode 代码值不匹配。

针对英语(美国)区域性“en-US”重新编译并执行这些代码时,将产生以下输出:

The CurrentCulture property is set to English (United States) 

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string aeble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string aeble is: -1

对字符串进行排序

Array 类提供了重载的 Sort() 方法,应用程序可根据 CurrentCulture 属性使用该方法对数组进行排序。在下面的示例中,将创建一个由三个字符串组成的数组。首先,将 CurrentCulture 属性设置为英语(美国)“en-US”,并调用 Sort() 方法。结果排序顺序基于英语(美国)区域性的排序约定。接下来,将 CurrentCulture 属性设置为丹麦语(丹麦)“da-DK”,再次调用 Array.Sort 方法。请注意,结果排序顺序与使用“en-US”时的结果是不一样的,因为使用的是“da-DK”区域性的排序约定。

Imports System
Imports System.Threading
Imports System.IO
Imports System.Globalization
Imports Microsoft.VisualBasic

Public Class TextToFile   
   Public Shared Sub Main()
      Dim str1 As [String] = "Apple"
      Dim str2 As [String] = "Æble"
      Dim str3 As [String] = "Zebra"
      
      ' Creates and initializes a new Array to store 
      ' these date/time objects.
      Dim stringArray As Array = Array.CreateInstance(GetType([String]), _
         3)
      stringArray.SetValue(str1, 0)
      stringArray.SetValue(str2, 1)
      stringArray.SetValue(str3, 2)
      
      ' Displays the values of the Array.
      Console.WriteLine(ControlChars.Newline + "The Array initially _
         contains the following strings:")
      PrintIndexAndValues(stringArray)
      
      ' Sets the CurrentCulture to "en-US".
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      ' Sorts the values of the Array.
      Array.Sort(stringArray)
      
      ' Displays the values of the Array.
      Console.WriteLine(ControlChars.Newline + "After sorting for the _
         culture ""en-US"":")
      PrintIndexAndValues(stringArray)
      
      ' Sets the CurrentCulture to "da-DK".
      Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
      ' Sort the values of the Array.
      Array.Sort(stringArray)
      
      ' Displays the values of the Array.
      Console.WriteLine(ControlChars.Newline + "After sorting for the _
         culture ""da-DK"":")
      PrintIndexAndValues(stringArray)
   End Sub

   Public Shared Sub PrintIndexAndValues(myArray As Array)
      Dim i As Integer
      For i = myArray.GetLowerBound(0) To myArray.GetUpperBound(0)
         Console.WriteLine(ControlChars.Tab + "[{0}]:" + _
            ControlChars.Tab + "{1}", i, myArray.GetValue(i))
      Next i
   End Sub 
End Class
using System;
using System.Threading;
using System.Globalization;

public class ArraySort 
{
   public static void Main(String[] args) 
   {
      String str1 = "Apple";
      String str2 = "Æble";
      String str3 = "Zebra";

      // Creates and initializes a new Array to store the strings.
      Array stringArray = Array.CreateInstance( typeof(String), 3 );
      stringArray.SetValue(str1, 0 );
      stringArray.SetValue(str2, 1 );
      stringArray.SetValue(str3, 2 );

      // Displays the values of the Array.
      Console.WriteLine( "\nThe Array initially contains the following 
            strings:" );
      PrintIndexAndValues(stringArray);

      // Sets the CurrentCulture to "en-US".
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      // Sort the values of the Array.
      Array.Sort(stringArray);

      // Displays the values of the Array.
      Console.WriteLine( "\nAfter sorting for the culture \"en-US\":" );
      PrintIndexAndValues(stringArray); 

      // Sets the CurrentCulture to "da-DK".
      Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
      // Sort the values of the Array.
      Array.Sort(stringArray);

      // Displays the values of the Array.
      Console.WriteLine( "\nAfter sorting for the culture \"da-DK\":" );
      PrintIndexAndValues(stringArray); 
   }
   public static void PrintIndexAndValues(Array myArray)  
   {
      for ( int i = myArray.GetLowerBound(0); i <= 
            myArray.GetUpperBound(0); i++ )
      Console.WriteLine( "\t[{0}]:\t{1}", i, myArray.GetValue( i ) );
   }
}

此代码产生下列输出:

The Array initially contains the following strings:
   [0]:   Apple
   [1]:   Æble
   [2]:   Zebra

After sorting for the culture "en-US":
   [0]:   Æble
   [1]:   Apple
   [2]:   Zebra

After sorting for the culture "da-DK":
   [0]:   Apple
   [1]:   Zebra
   [2]:   Æble

使用排序关键字

排序关键字用于支持区分区域性的排序。根据“Unicode 标准”,字符串中的每个字符都有若干类别给定的排序权重,包括字母、大小写和音调权重。排序关键字充当特定字符串的这些权重的储存库。例如,一个排序关键字可能包含一个字母权重字符串,后跟一个大小写权重字符串,依此类推。有关排序关键字概念的其他信息,请参见位于 www.unicode.org 的“Unicode 标准”。

在 .NET Framework 中,SortKey 类将字符串映射到它们的排序关键字,反之亦然。应用程序可以使用 GetSortKey() 方法为指定的字符串创建排序关键字。指定字符串的结果排序关键字是一个字节序列,它可能会因指定的 CurrentCultureCompareOptions 值的不同而不同。例如,如果在创建排序关键字时,应用程序指定值 IgnoreCase,则使用该排序关键字进行的字符串比较操作将忽略大小写。

为字符串创建排序关键字后,应用程序可以将该关键字作为参数传递给 SortKey 类提供的方法。Compare 方法可以对排序关键字进行比较。此方法执行简单的逐字节比较,因此,使用起来比 Compare() 快很多。在进行大量排序的应用程序中,通过为所用的所有字符串生成并存储排序关键字,可以提高性能。需要执行排序或比较操作时,应用程序可以使用这些排序关键字,而不必使用字符串。

下面的代码示例在 CurrentCulture 设置为“da-DK”时,为两个字符串创建排序关键字。它使用 SortKey.Compare 方法比较这两个字符串,并显示结果。如果 string1 小于 string2,该方法返回一个负整数;如果 string1 和 string2 相等,则返回零 (0);如果 string1 大于 string2,则返回一个正整数。接下来,将 CurrentCulture 属性设置为“en-US”,并为这些字符串创建排序关键字。然后对字符串的排序关键字进行比较并显示结果。请注意,排序结果因 CurrentCulture 的设置的不同而不同。尽管下面代码示例的结果与本主题前面比较字符串示例中这些字符串的比较结果相同,但使用 SortKey.Compare 方法比使用 String.Compare 方法更快。

Imports System
Imports System.Threading
Imports System.Globalization
Imports Microsoft.VisualBasic

Public Class SortKeySample
   Public Shared Sub Main()
      Dim str1 As [String] = "Apple"
      Dim str2 As [String] = "Æble"
      
      ' Sets the CurrentCulture to "da-DK".
      Dim dk As New CultureInfo("da-DK")
      Thread.CurrentThread.CurrentCulture = dk
      
      ' Creates a culturally sensitive sort key for str1.
      Dim sc1 As SortKey = dk.CompareInfo.GetSortKey(str1)
      ' Create a culturally sensitive sort key for str2.
      Dim sc2 As SortKey = dk.CompareInfo.GetSortKey(str2)
      
      ' Compares the two sort keys and display the results.
      Dim result1 As Integer = SortKey.Compare(sc1, sc2)
      Console.WriteLine(ControlChars.Newline + "When the CurrentCulture _
         is ""da-DK""," + ControlChars.Newline + " the result of _
         comparing {0} with {1} is: {2}", str1, str2, result1)
      
      ' Sets the CurrentCulture to "en-US".
      Dim enus As New CultureInfo("en-US")
      Thread.CurrentThread.CurrentCulture = enus
      
      ' Creates a culturally sensitive sort key for str1.
      Dim sc3 As SortKey = enus.CompareInfo.GetSortKey(str1)
      ' Create a culturally sensitive sort key for str1.
      Dim sc4 As SortKey = enus.CompareInfo.GetSortKey(str2)
      
      ' Compares the two sort keys and display the results.
      Dim result2 As Integer = SortKey.Compare(sc3, sc4)
      Console.WriteLine(ControlChars.Newline + "When the CurrentCulture _
         is ""en-US""," + ControlChars.Newline + " the result of _
         comparing {0} with {1} is: {2}", str1, str2, result2)
   End Sub
End Class
using System;
using System.Threading;
using System.Globalization;

public class SortKeySample 
{
   public static void Main(String[] args) 
   {
      String str1 = "Apple";
      String str2 = "Æble";

      // Sets the CurrentCulture to "da-DK".
      CultureInfo dk = new CultureInfo("da-DK");
      Thread.CurrentThread.CurrentCulture = dk;

      // Creates a culturally sensitive sort key for str1.
      SortKey sc1 = dk.CompareInfo.GetSortKey(str1);
      // Create a culturally sensitive sort key for str2.
      SortKey sc2 = dk.CompareInfo.GetSortKey(str2);

      // Compares the two sort keys and display the results.
      int result1 = SortKey.Compare(sc1, sc2);
      Console.WriteLine("\nWhen the CurrentCulture is \"da-DK\",\nthe 
            result of comparing {0} with {1} is: {2}", str1, str2, 
            result1);

      // Sets the CurrentCulture to "en-US".
      CultureInfo enus = new CultureInfo("en-US");
      Thread.CurrentThread.CurrentCulture = enus ;

      // Creates a culturally sensitive sort key for str1.
      SortKey sc3 = enus.CompareInfo.GetSortKey(str1);
      // Create a culturally sensitive sort key for str1.
      SortKey sc4 = enus.CompareInfo.GetSortKey(str2);

      // Compares the two sort keys and display the results.
      int result2 = SortKey.Compare(sc3, sc4);
      Console.WriteLine("\nWhen the CurrentCulture is \"en-US\",\nthe 
            result of comparing {0} with {1} is: {2}", str1, str2, 
            result2);
   }
}

此代码产生下列输出:

When the CurrentCulture is "da-DK", 
the result of comparing Apple with Æble is: -1

When the CurrentCulture is "en-US", 
the result of comparing Apple with Æble is: 1

正常化

在排序之前,应用程序可以将字符串正常化为大写或小写。字符串排序和大小写转换规则是语言特定的。例如,即使在拉丁语系中,也存在不同的撰写和排序规则。只有在少数几种语言(包括英语)中,排序顺序和码位顺序是匹配的,例如 A [65] 位于 B [66] 之前。

应用程序不应依赖码位来执行精确的排序和字符串比较。此外,.NET Framework 并不强制或保证执行特定形式的正常化。您负责在所开发的应用程序中执行适当的正常化。

有关字符串正常化的更多信息,请参见正常化和排序

请参见

概念

不区分区域性的字符串操作

正常化和排序

其他资源

编码和本地化