Práticas recomendadas para o uso de cadeias de caracteres no .NETBest Practices for Using Strings in .NET

O .NET dá um amplo suporte para desenvolvimento de aplicativos localizados e globalizados e torna mais fácil aplicar as convenções da cultura atual ou de uma cultura específica ao executar operações comuns, como a classificação e a exibição cadeias de caracteres..NET provides extensive support for developing localized and globalized applications, and makes it easy to apply the conventions of either the current culture or a specific culture when performing common operations such as sorting and displaying strings. Mas a classificação ou a comparação de cadeias de caracteres nem sempre é uma operação que leva em conta a cultura.But sorting or comparing strings is not always a culture-sensitive operation. Por exemplo, cadeias de caracteres que são usadas internamente por um aplicativo normalmente devem ser manipuladas de maneira idêntica em todas as culturas.For example, strings that are used internally by an application typically should be handled identically across all cultures. Quando os dados de cadeias de caracteres culturalmente independentes, como marcações XML, marcações HTML, nomes de usuário, caminhos de arquivo e nomes de objetos do sistema, são interpretados como se levassem em conta a cultura, o código do aplicativo pode estar sujeito a bugs sutis, desempenho ruim e, em alguns casos, problemas de segurança.When culturally independent string data, such as XML tags, HTML tags, user names, file paths, and the names of system objects, are interpreted as if they were culture-sensitive, application code can be subject to subtle bugs, poor performance, and, in some cases, security issues.

Este tópico examina os métodos de classificação, comparação e o uso de maiúsculas e minúsculas de cadeias de caracteres no .NET, apresenta recomendações para a seleção de um método de manipulação de cadeia de caracteres adequado e fornece informações adicionais sobre os métodos de manipulação de cadeia de caracteres.This topic examines the string sorting, comparison, and casing methods in .NET, presents recommendations for selecting an appropriate string-handling method, and provides additional information about string-handling methods. Ela também examina como os dados formatados, como dados numéricos e dados de data e hora, são manipulados para exibição e armazenamento.It also examines how formatted data, such as numeric data and date and time data, is handled for display and for storage.

Esse tópico contém as seguintes seções:This topic contains the following sections:

Recomendações para Uso da Cadeia de CaracteresRecommendations for String Usage

Ao desenvolver com o .NET, siga estas recomendações simples quando usar cadeias de caracteres:When you develop with .NET, follow these simple recommendations when you use strings:

Evite as práticas a seguir ao usar cadeias de caracteres:Avoid the following practices when you use strings:

  • Não use sobrecargas que não especificam explicita ou implicitamente as regras de comparação de cadeias de caracteres para operações de cadeia de caracteres.Do not use overloads that do not explicitly or implicitly specify the string comparison rules for string operations.

  • Não use operações de cadeia de caracteres com base em StringComparison.InvariantCulture na maioria dos casos.Do not use string operations based on StringComparison.InvariantCulture in most cases. Uma das poucas exceções é quando você persiste dados de forma linguisticamente significativa, mas independente de cultura.One of the few exceptions is when you are persisting linguistically meaningful but culturally agnostic data.

  • Não use uma sobrecarga dos métodos String.Compare ou CompareTo e teste para um valor retornado de zero para determinar se duas cadeias de caracteres são iguais.Do not use an overload of the String.Compare or CompareTo method and test for a return value of zero to determine whether two strings are equal.

  • Não use a formatação que leva em conta a cultura para persistir dados numéricos ou dados de data e hora no formato de cadeia de caracteres.Do not use culture-sensitive formatting to persist numeric data or date and time data in string form.

Voltar ao inícioBack to top

Especificando Comparações da Cadeia de Caracteres ExplicitamenteSpecifying String Comparisons Explicitly

A maioria dos métodos de manipulação de cadeia de caracteres no .NET é sobrecarregada.Most of the string manipulation methods in .NET are overloaded. Normalmente, uma ou mais sobrecargas aceitam as configurações padrão, enquanto outras não aceitam nenhum padrão e definem a maneira exata em que as cadeias de caracteres devem ser comparadas ou manipuladas.Typically, one or more overloads accept default settings, whereas others accept no defaults and instead define the precise way in which strings are to be compared or manipulated. A maioria dos métodos que não dependem de padrões inclui um parâmetro do tipo StringComparison, que é uma enumeração que especifica explicitamente as regras de comparação de cadeia de caracteres por cultura e maiúsculas e minúsculas.Most of the methods that do not rely on defaults include a parameter of type StringComparison, which is an enumeration that explicitly specifies rules for string comparison by culture and case. A tabela a seguir descreve os membros de enumeração StringComparison.The following table describes the StringComparison enumeration members.

Membro de StringComparisonStringComparison member DescriçãoDescription
CurrentCulture Executa uma comparação que diferencia maiúsculas de minúsculas usando a cultura atual.Performs a case-sensitive comparison using the current culture.
CurrentCultureIgnoreCase Executa uma comparação que não diferencia maiúsculas de minúsculas usando a cultura atual.Performs a case-insensitive comparison using the current culture.
InvariantCulture Executa uma comparação que diferencia maiúsculas de minúsculas usando a cultura invariável.Performs a case-sensitive comparison using the invariant culture.
InvariantCultureIgnoreCase Executa uma comparação que não diferencia maiúsculas de minúsculas usando a cultura invariável.Performs a case-insensitive comparison using the invariant culture.
Ordinal Executa uma comparação ordinal.Performs an ordinal comparison.
OrdinalIgnoreCase Executa uma comparação ordinal que não diferencia maiúsculas de minúsculas.Performs a case-insensitive ordinal comparison.

Por exemplo, o método IndexOf, que retorna um índice de uma subcadeia de caracteres em um objeto String que corresponde a um caractere ou cadeia de caracteres, tem nove sobrecargas:For example, the IndexOf method, which returns the index of a substring in a String object that matches either a character or a string, has nine overloads:

É recomendável que você selecione uma sobrecarga que não usa valores padrão, pelos seguintes motivos:We recommend that you select an overload that does not use default values, for the following reasons:

  • Algumas sobrecargas com parâmetros padrão (aqueles que pesquisam um Char na instância de cadeia de caracteres) realizam uma comparação ordinal, enquanto outras (aquelas que pesquisam uma cadeia de caracteres na instância de cadeia de caracteres) levam em consideração a cultura.Some overloads with default parameters (those that search for a Char in the string instance) perform an ordinal comparison, whereas others (those that search for a string in the string instance) are culture-sensitive. É difícil lembrar qual método usa o valor padrão e é fácil confundir as sobrecargas.It is difficult to remember which method uses which default value, and easy to confuse the overloads.

  • A intenção do código que depende de valores padrão para chamadas de método não é clara.The intent of the code that relies on default values for method calls is not clear. No exemplo a seguir, que se baseia em padrões, é difícil saber se o desenvolvedor realmente planejava uma comparação ordinal ou linguística de duas cadeias de caracteres ou se uma diferença entre maiúsculas e minúsculas entre protocol e “http” pode fazer com que o teste de igualdade retorne false.In the following example, which relies on defaults, it is difficult to know whether the developer actually intended an ordinal or a linguistic comparison of two strings, or whether a case difference between protocol and "http" might cause the test for equality to return false.

    string protocol = GetProtocol(url);       
    if (String.Equals(protocol, "http")) {
       // ...Code to handle HTTP protocol.
    }
    else {
       throw new InvalidOperationException();
    }
    
    Dim protocol As String = GetProtocol(url)       
    If String.Equals(protocol, "http") Then
       ' ...Code to handle HTTP protocol.
    Else
       Throw New InvalidOperationException()
    End If   
    

Em geral, é recomendável que você chame um método que não se baseie em padrões, pois ele torna a intenção do código clara.In general, we recommend that you call a method that does not rely on defaults, because it makes the intent of the code unambiguous. Isso, por sua vez, torna o código mais legível e fácil de depurar e manter.This, in turn, makes the code more readable and easier to debug and maintain. O exemplo a seguir aborda as questões levantadas sobre o exemplo anterior.The following example addresses the questions raised about the previous example. Ele deixa claro que a comparação ordinal é usada e que as diferenças de maiúsculas e minúsculas são ignoradas.It makes it clear that ordinal comparison is used and that differences in case are ignored.

string protocol = GetProtocol(url);       
if (String.Equals(protocol, "http", StringComparison.OrdinalIgnoreCase)) {
   // ...Code to handle HTTP protocol.
}
else {
   throw new InvalidOperationException();
}
Dim protocol As String = GetProtocol(url)       
If String.Equals(protocol, "http", StringComparison.OrdinalIgnoreCase) Then
   ' ...Code to handle HTTP protocol.
Else
   Throw New InvalidOperationException()
End If   

Voltar ao inícioBack to top

Os Detalhes de Comparação da Cadeia de CaracteresThe Details of String Comparison

A comparação de cadeia de caracteres é o centro de muitas operações relacionadas à cadeia de caracteres, especialmente a classificação e teste de igualdade.String comparison is the heart of many string-related operations, particularly sorting and testing for equality. Cadeias de caracteres são classificadas em uma determinada ordem: Se "meu" aparecer antes de "cadeia de caracteres" em uma lista classificada de cadeias de caracteres, "meu" deverá se comparar como menor ou igual a "cadeia de caracteres".Strings sort in a determined order: If "my" appears before "string" in a sorted list of strings, "my" must compare less than or equal to "string". Além disso, a comparação define implicitamente a igualdade.Additionally, comparison implicitly defines equality. A operação de comparação retorna zero para cadeias de caracteres que considerar iguais.The comparison operation returns zero for strings it deems equal. Uma boa interpretação é que nenhuma cadeia de caracteres é menor que a outra.A good interpretation is that neither string is less than the other. Operações mais significativas envolvendo cadeias de caracteres incluem um ou ambos destes procedimentos: comparação com outra cadeia de caracteres e execução de uma operação de classificação bem definida.Most meaningful operations involving strings include one or both of these procedures: comparing with another string, and executing a well-defined sort operation.

Observação

Você pode baixar as Tabelas de peso de classificação, um conjunto de arquivos de texto que contêm informações sobre os pesos de caracteres usados em operações de classificação e comparação dos sistemas operacionais Windows, e a Tabela de elemento de ordenação Unicode padrão, a versão mais recente da tabela de peso de classificação para Linux e macOS.You can download the Sorting Weight Tables, a set of text files that contain information on the character weights used in sorting and comparison operations for Windows operating systems, and the Default Unicode Collation Element Table, the latest version of the sort weight table for Linux and macOS. A versão específica da tabela de peso de classificação do Linux e macOS depende da versão das bibliotecas de Componentes internacionais para Unicode instaladas no sistema.The specific version of the sort weight table on Linux and macOS depends on the version of the International Components for Unicode libraries installed on the system. Para obter informações sobre versões de ICU e as versões Unicode que elas implementam, veja Baixar ICU.For information on ICU versions and the Unicode versions that they implement, see Downloading ICU.

No entanto, avaliar duas cadeias de caracteres quanto à igualdade ou ordem de classificação não gera um único resultado correto, o resultado depende dos critérios usados para comparar as cadeias de caracteres.However, evaluating two strings for equality or sort order does not yield a single, correct result; the outcome depends on the criteria used to compare the strings. Em particular, as comparações de cadeia de caracteres ordinais ou baseadas no uso de maiúsculas e minúsculas e convenções classificação da cultura atual ou da cultura invariável (uma cultura independente de localidade com base no idioma inglês) podem gerar resultados diferentes.In particular, string comparisons that are ordinal or that are based on the casing and sorting conventions of the current culture or the invariant culture (a locale-agnostic culture based on the English language) may produce different results.

Além disso, comparações de cadeia de caracteres usando versões diferentes do .NET ou usando o .NET em diferentes sistemas operacionais ou versões do sistema operacional podem retornar resultados diferentes.In addition, string comparisons using different versions of .NET or using .NET on different operating systems or operating system versions may return different results. Para obter mais informações, veja Cadeias de caracteres e o padrão Unicode.For more information, see Strings and the Unicode Standard.

Comparações da Cadeia de Caracteres que Usam a Cultura AtualString Comparisons that Use the Current Culture

Um critério envolve o uso das convenções da cultura atual ao comparar cadeias de caracteres.One criterion involves using the conventions of the current culture when comparing strings. As comparações que se baseiam na cultura atual usam a localidade ou a cultura atual do thread.Comparisons that are based on the current culture use the thread's current culture or locale. Se a cultura não for definida pelo usuário, o padrão será a configuração na janela Opções Regionais no Painel de Controle.If the culture is not set by the user, it defaults to the setting in the Regional Options window in Control Panel. Você deve sempre usar comparações que se baseiam na cultura atual quando os dados forem linguisticamente relevantes e quando eles refletirem a interação do usuário que leva em conta a cultura.You should always use comparisons that are based on the current culture when data is linguistically relevant, and when it reflects culture-sensitive user interaction.

No entanto, o comportamento da comparação e do uso de maiúsculas e minúsculas no .NET muda quando a cultura muda.However, comparison and casing behavior in .NET changes when the culture changes. Isso acontece quando um aplicativo é executado em um computador que tem uma cultura diferente do computador em que o aplicativo foi desenvolvido ou quando o thread em execução muda sua cultura.This happens when an application executes on a computer that has a different culture than the computer on which the application was developed, or when the executing thread changes its culture. Esse comportamento é intencional, mas permanece não óbvio para muitos desenvolvedores.This behavior is intentional, but it remains non-obvious to many developers. O exemplo a seguir ilustra as diferenças na ordem de classificação entre as culturas de inglês dos EUA ("en-US") e sueco ("sv-SE").The following example illustrates differences in sort order between the U.S. English ("en-US") and Swedish ("sv-SE") cultures. Observe que as palavras "ångström", "Windows" e "Visual Studio" aparecem em posições diferentes nas matrizes de cadeias de caracteres classificadas.Note that the words "ångström", "Windows", and "Visual Studio" appear in different positions in the sorted string arrays.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      string[] values= { "able", "ångström", "apple", "Æble", 
                         "Windows", "Visual Studio" };
      Array.Sort(values);
      DisplayArray(values);

      // Change culture to Swedish (Sweden).
      string originalCulture = CultureInfo.CurrentCulture.Name;
      Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-SE");
      Array.Sort(values);
      DisplayArray(values);

      // Restore the original culture.
      Thread.CurrentThread.CurrentCulture = new CultureInfo(originalCulture);
    }
    
    private static void DisplayArray(string[] values)
    {
      Console.WriteLine("Sorting using the {0} culture:",  
                        CultureInfo.CurrentCulture.Name);
      foreach (string value in values)
         Console.WriteLine("   {0}", value);

      Console.WriteLine();
    }
}
// The example displays the following output:
//       Sorting using the en-US culture:
//          able
//          Æble
//          ångström
//          apple
//          Visual Studio
//          Windows
//       
//       Sorting using the sv-SE culture:
//          able
//          Æble
//          apple
//          Windows
//          Visual Studio
//          ångström
Imports System.Globalization
Imports System.Threading

Module Example
   Public Sub Main()
      Dim values() As String = { "able", "ångström", "apple", _
                                 "Æble", "Windows", "Visual Studio" }
      Array.Sort(values)
      DisplayArray(values)

      ' Change culture to Swedish (Sweden).
      Dim originalCulture As String = CultureInfo.CurrentCulture.Name
      Thread.CurrentThread.CurrentCulture = New CultureInfo("sv-SE")
      Array.Sort(values)
      DisplayArray(values)

      ' Restore the original culture.
      Thread.CurrentThread.CurrentCulture = New CultureInfo(originalCulture)
    End Sub
    
    Private Sub DisplayArray(values() As String)
      Console.WRiteLine("Sorting using the {0} culture:", _ 
                        CultureInfo.CurrentCulture.Name)
      For Each value As String In values
         Console.WriteLine("   {0}", value)
      Next
      Console.WriteLine()   
    End Sub
End Module
' The example displays the following output:
'       Sorting using the en-US culture:
'          able
'          Æble
'          ångström
'          apple
'          Visual Studio
'          Windows
'       
'       Sorting using the sv-SE culture:
'          able
'          Æble
'          apple
'          Windows
'          Visual Studio
'          ångström

As comparações que não diferenciam maiúsculas de minúsculas que usam a cultura atual são iguais às comparações que levam em conta a cultura, exceto que elas ignoram as maiúsculas e minúsculas conforme determinado pela cultura atual do thread.Case-insensitive comparisons that use the current culture are the same as culture-sensitive comparisons, except that they ignore case as dictated by the thread's current culture. Esse comportamento pode se manifestar em ordens de classificação também.This behavior may manifest itself in sort orders as well.

As comparações que usam a semântica de cultura atual são o padrão para os seguintes métodos:Comparisons that use current culture semantics are the default for the following methods:

Em qualquer caso, é recomendável que você chame uma sobrecarga que tenha um parâmetro StringComparison para deixar a intenção da chamada do método clara.In any case, we recommend that you call an overload that has a StringComparison parameter to make the intent of the method call clear.

Bugs sutis e não tão sutis podem surgir quando dados de cadeias de caracteres não linguísticas são interpretados linguisticamente ou quando os dados da cadeia de caracteres de uma cultura específica são interpretados usando as convenções de outra cultura.Subtle and not so subtle bugs can emerge when non-linguistic string data is interpreted linguistically, or when string data from a particular culture is interpreted using the conventions of another culture. O exemplo canônico é o problema do I turco.The canonical example is the Turkish-I problem.

Para quase todos os alfabetos latinos, incluindo o do inglês dos EUA, o caractere "i" (\u0069) é a versão em letra minúscula do caractere "I" (\u0049).For nearly all Latin alphabets, including U.S. English, the character "i" (\u0069) is the lowercase version of the character "I" (\u0049). Essa regra de maiúsculas e minúsculas rapidamente se torna o padrão para alguém programando em tal cultura.This casing rule quickly becomes the default for someone programming in such a culture. No entanto, o alfabeto turco ("tr-TR") inclui um caractere "I com um ponto", "İ" (\u0130), que é a versão maiúscula de "i".However, the Turkish ("tr-TR") alphabet includes an "I with a dot" character "İ" (\u0130), which is the capital version of "i". O turco também inclui um caractere minúsculo "i sem um ponto", "ı" (\u0131), que em maiúscula é “I”.Turkish also includes a lowercase "i without a dot" character, "ı" (\u0131), which capitalizes to "I". Esse comportamento também ocorre na cultura azerbaijana ("az").This behavior occurs in the Azerbaijani ("az") culture as well.

Portanto, as suposições feitas sobre a colocação do "i" em maiúscula ou do "I" em minúscula não são válidas entre todas as culturas.Therefore, assumptions made about capitalizing "i" or lowercasing "I" are not valid among all cultures. Se você usar as sobrecargas padrão para rotinas de comparação de cadeias de caracteres, elas estarão sujeitas à variação entre culturas.If you use the default overloads for string comparison routines, they will be subject to variance between cultures. Se os dados a serem comparados são forem linguísticos, o uso das sobrecargas padrão pode gerar resultados indesejáveis, como a tentativa a seguir de realizar uma comparação que não diferencia maiúsculas de minúsculas das cadeias de caracteres “file” e “FILE” ilustra.If the data to be compared is non-linguistic, using the default overloads can produce undesirable results, as the following attempt to perform a case-insensitive comparison of the strings "file" and "FILE" illustrates.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      string fileUrl = "file";
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      Console.WriteLine("Culture = {0}",
                        Thread.CurrentThread.CurrentCulture.DisplayName);
      Console.WriteLine("(file == FILE) = {0}", 
                       fileUrl.StartsWith("FILE", true, null));
      Console.WriteLine();
      
      Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
      Console.WriteLine("Culture = {0}",
                        Thread.CurrentThread.CurrentCulture.DisplayName);
      Console.WriteLine("(file == FILE) = {0}", 
                        fileUrl.StartsWith("FILE", true, null));
   }
}
// The example displays the following output:
//       Culture = English (United States)
//       (file == FILE) = True
//       
//       Culture = Turkish (Turkey)
//       (file == FILE) = False
Imports System.Globalization
Imports System.Threading

Module Example
   Public Sub Main()
      Dim fileUrl = "file"
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      Console.WriteLine("Culture = {0}", _
                        Thread.CurrentThread.CurrentCulture.DisplayName)
      Console.WriteLine("(file == FILE) = {0}", _ 
                       fileUrl.StartsWith("FILE", True, Nothing))
      Console.WriteLine()
      
      Thread.CurrentThread.CurrentCulture = New CultureInfo("tr-TR")
      Console.WriteLine("Culture = {0}", _
                        Thread.CurrentThread.CurrentCulture.DisplayName)
      Console.WriteLine("(file == FILE) = {0}", _ 
                        fileUrl.StartsWith("FILE", True, Nothing))
   End Sub
End Module
' The example displays the following output:
'       Culture = English (United States)
'       (file == FILE) = True
'       
'       Culture = Turkish (Turkey)
'       (file == FILE) = False

Essa comparação pode causar problemas significativos se a cultura for usada inadvertidamente nas configurações sensíveis à segurança, como no exemplo a seguir.This comparison could cause significant problems if the culture is inadvertently used in security-sensitive settings, as in the following example. Uma chamada de método, como IsFileURI("file:") retorna true se a cultura atual for inglês dos EUA, mas false se a cultura atual for turco.A method call such as IsFileURI("file:") returns true if the current culture is U.S. English, but false if the current culture is Turkish. Assim, em sistemas turcos, alguém poderia driblar as medidas de segurança que bloqueiam o acesso a URIs que não diferenciam maiúsculas de minúsculas que começam com “FILE:”.Thus, on Turkish systems, someone could circumvent security measures that block access to case-insensitive URIs that begin with "FILE:".

public static bool IsFileURI(String path) 
{
   return path.StartsWith("FILE:", true, null);
}
Public Shared Function IsFileURI(path As String) As Boolean 
   Return path.StartsWith("FILE:", True, Nothing)
End Function

Nesse caso, como "file:" deve ser interpretado como um identificador não linguístico que não leva em conta a cultura, o código deveria ser escrito como mostrado no exemplo a seguir.In this case, because "file:" is meant to be interpreted as a non-linguistic, culture-insensitive identifier, the code should instead be written as shown in the following example.

public static bool IsFileURI(string path) 
{
   return path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase);
}
Public Shared Function IsFileURI(path As String) As Boolean 
    Return path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase)
End Function

Operações Ordinais da Cadeia de CaracteresOrdinal String Operations

Especificar o valor StringComparison.Ordinal ou StringComparison.OrdinalIgnoreCase em uma chamada de método significa uma comparação não linguística em que os recursos de linguagens naturais são ignorados.Specifying the StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase value in a method call signifies a non-linguistic comparison in which the features of natural languages are ignored. Os métodos que são invocados com esses valores de StringComparison baseiam as decisões de operação da cadeia de caracteres em comparações de byte simples em vez de no uso de maiúsculas e minúsculas ou tabelas de equivalência que são parametrizadas pela cultura.Methods that are invoked with these StringComparison values base string operation decisions on simple byte comparisons instead of casing or equivalence tables that are parameterized by culture. Na maioria dos casos, essa abordagem se adapta melhor à interpretação pretendida de cadeias de caracteres, enquanto torna o código mais rápido e confiável.In most cases, this approach best fits the intended interpretation of strings while making code faster and more reliable.

Comparações ordinais são comparações de cadeia de caracteres nas quais cada byte de cada cadeia de caracteres é comparado sem a interpretação linguística, por exemplo, “windows” não corresponde a “Windows”.Ordinal comparisons are string comparisons in which each byte of each string is compared without linguistic interpretation; for example, "windows" does not match "Windows". Isso é basicamente uma chamada para a função strcmp de tempo de execução de C.This is essentially a call to the C runtime strcmp function. Use essa comparação quando o contexto determinar que as cadeias de caracteres devem corresponder exatamente ou exigir uma política de correspondência conservadora.Use this comparison when the context dictates that strings should be matched exactly or demands conservative matching policy. Além disso, a comparação ordinal é a operação de comparação mais rápida porque ela não aplica nenhuma regra linguística ao determinar um resultado.Additionally, ordinal comparison is the fastest comparison operation because it applies no linguistic rules when determining a result.

As cadeias de caracteres no .NET podem conter caracteres nulos inseridos.Strings in .NET can contain embedded null characters. Uma das diferenças mais clara entre a comparação ordinal e a que leva em conta a cultura (incluindo comparações que usam a cultura invariável) diz respeito à manipulação de caracteres nulos inseridos em uma cadeia de caracteres.One of the clearest differences between ordinal and culture-sensitive comparison (including comparisons that use the invariant culture) concerns the handling of embedded null characters in a string. Esses caracteres são ignorados quando você usa os métodos String.Compare e String.Equals para realizar comparações que levam em conta a cultura (incluindo comparações que usam a cultura invariável).These characters are ignored when you use the String.Compare and String.Equals methods to perform culture-sensitive comparisons (including comparisons that use the invariant culture). Como resultado, em comparações que levam em conta a cultura, cadeias de caracteres que contêm caracteres nulos inseridos podem ser consideradas iguais a cadeias de caracteres que não contêm.As a result, in culture-sensitive comparisons, strings that contain embedded null characters can be considered equal to strings that do not.

Importante

Embora os métodos de comparação de cadeia de caracteres ignorem caracteres nulos inseridos, os métodos de pesquisa de cadeia de caracteres, como String.Contains, String.EndsWith, String.IndexOf, String.LastIndexOf e String.StartsWith, não o fazem.Although string comparison methods disregard embedded null characters, string search methods such as String.Contains, String.EndsWith, String.IndexOf, String.LastIndexOf, and String.StartsWith do not.

O exemplo a seguir executa uma comparação que leva em conta a cultura da cadeia de caracteres "Aa" com uma cadeia de caracteres semelhante que contém vários caracteres nulos inseridos entre "A" e "a" e mostra como as duas cadeias de caracteres são consideradas iguais.The following example performs a culture-sensitive comparison of the string "Aa" with a similar string that contains several embedded null characters between "A" and "a", and shows how the two strings are considered equal.

using System;

public class Example
{
   public static void Main()
   {
      string str1 = "Aa";
      string str2 = "A" + new String('\u0000', 3) + "a";
      Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", 
                        str1, ShowBytes(str1), str2, ShowBytes(str2));
      Console.WriteLine("   With String.Compare:");
      Console.WriteLine("      Current Culture: {0}", 
                        String.Compare(str1, str2, StringComparison.CurrentCulture));
      Console.WriteLine("      Invariant Culture: {0}", 
                        String.Compare(str1, str2, StringComparison.InvariantCulture));

      Console.WriteLine("   With String.Equals:");
      Console.WriteLine("      Current Culture: {0}", 
                        String.Equals(str1, str2, StringComparison.CurrentCulture));
      Console.WriteLine("      Invariant Culture: {0}", 
                        String.Equals(str1, str2, StringComparison.InvariantCulture));
   }
   
   private static string ShowBytes(string str)
   {
      string hexString = String.Empty;
      for (int ctr = 0; ctr < str.Length; ctr++)
      {
         string result = String.Empty;
         result = Convert.ToInt32(str[ctr]).ToString("X4");
         result = " " + result.Substring(0,2) + " " + result.Substring(2, 2);
         hexString += result;
      }
      return hexString.Trim();
   }
}
// The example displays the following output:
//    Comparing 'Aa' (00 41 00 61) and 'A   a' (00 41 00 00 00 00 00 00 00 61):
//       With String.Compare:
//          Current Culture: 0
//          Invariant Culture: 0
//       With String.Equals:
//          Current Culture: True
//          Invariant Culture: True
Module Example
   Public Sub Main()
      Dim str1 As String = "Aa"
      Dim str2 As String = "A" + New String(Convert.ToChar(0), 3) + "a"
      Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", _
                        str1, ShowBytes(str1), str2, ShowBytes(str2))
      Console.WriteLine("   With String.Compare:")
      Console.WriteLine("      Current Culture: {0}", _
                        String.Compare(str1, str2, StringComparison.CurrentCulture))
      Console.WriteLine("      Invariant Culture: {0}", _
                        String.Compare(str1, str2, StringComparison.InvariantCulture))

      Console.WriteLine("   With String.Equals:")
      Console.WriteLine("      Current Culture: {0}", _
                        String.Equals(str1, str2, StringComparison.CurrentCulture))
      Console.WriteLine("      Invariant Culture: {0}", _
                        String.Equals(str1, str2, StringComparison.InvariantCulture))
   End Sub
   
   Private Function ShowBytes(str As String) As String
      Dim hexString As String = String.Empty
      For ctr As Integer = 0 To str.Length - 1
         Dim result As String = String.Empty
         result = Convert.ToInt32(str.Chars(ctr)).ToString("X4")
         result = " " + result.Substring(0,2) + " " + result.Substring(2, 2)
         hexString += result
      Next
      Return hexString.Trim()
   End Function
End Module

No entanto, as cadeias de caracteres não são consideradas iguais ao usar a comparação ordinal, como mostra o exemplo a seguir.However, the strings are not considered equal when you use ordinal comparison, as the following example shows.

Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", 
                  str1, ShowBytes(str1), str2, ShowBytes(str2));
Console.WriteLine("   With String.Compare:");
Console.WriteLine("      Ordinal: {0}", 
                  String.Compare(str1, str2, StringComparison.Ordinal));

Console.WriteLine("   With String.Equals:");
Console.WriteLine("      Ordinal: {0}", 
                  String.Equals(str1, str2, StringComparison.Ordinal));
// The example displays the following output:
//    Comparing 'Aa' (00 41 00 61) and 'A   a' (00 41 00 00 00 00 00 00 00 61):
//       With String.Compare:
//          Ordinal: 97
//       With String.Equals:
//          Ordinal: False
Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", _
                  str1, ShowBytes(str1), str2, ShowBytes(str2))
Console.WriteLine("   With String.Compare:")
Console.WriteLine("      Ordinal: {0}", _
                  String.Compare(str1, str2, StringComparison.Ordinal))

Console.WriteLine("   With String.Equals:")
Console.WriteLine("      Ordinal: {0}", _
                  String.Equals(str1, str2, StringComparison.Ordinal))
' The example displays the following output:
'    Comparing 'Aa' (00 41 00 61) and 'A   a' (00 41 00 00 00 00 00 00 00 61):
'       With String.Compare:
'          Ordinal: 97
'       With String.Equals:
'          Ordinal: False

As comparações ordinais que não diferenciam maiúsculas de minúsculas são a próxima abordagem conservadora.Case-insensitive ordinal comparisons are the next most conservative approach. Essas comparações ignoram a maioria das maiúsculas e minúsculas, por exemplo, "windows" corresponde a "Windows".These comparisons ignore most casing; for example, "windows" matches "Windows". Ao lidar com caracteres ASCII, essa política é equivalente a StringComparison.Ordinal, exceto que ela ignora as maiúsculas e minúsculas de ASCII normais.When dealing with ASCII characters, this policy is equivalent to StringComparison.Ordinal, except that it ignores the usual ASCII casing. Portanto, qualquer caractere em [A, Z] (\u0041-\u005A) corresponde ao caractere correspondente em [a,z] (\u0061-\007A).Therefore, any character in [A, Z] (\u0041-\u005A) matches the corresponding character in [a,z] (\u0061-\007A). As maiúsculas e minúsculas fora do intervalo de ASCII usam as tabelas de cultura invariável.Casing outside the ASCII range uses the invariant culture's tables. Portanto, a comparação a seguir:Therefore, the following comparison:

String.Compare(strA, strB, StringComparison.OrdinalIgnoreCase);
String.Compare(strA, strB, StringComparison.OrdinalIgnoreCase)

é equivalente a (mas mais rápida do que) esta comparação:is equivalent to (but faster than) this comparison:

String.Compare(strA.ToUpperInvariant(), strB.ToUpperInvariant(), 
               StringComparison.Ordinal);
String.Compare(strA.ToUpperInvariant(), strB.ToUpperInvariant(), 
               StringComparison.Ordinal)

Essas comparações ainda são muito rápidas.These comparisons are still very fast.

Observação

O comportamento de cadeia de caracteres do sistema de arquivos, chaves do Registro e valores e variáveis de ambiente é melhor representado por StringComparison.OrdinalIgnoreCase.The string behavior of the file system, registry keys and values, and environment variables is best represented by StringComparison.OrdinalIgnoreCase.

StringComparison.Ordinal e StringComparison.OrdinalIgnoreCase usam os valores binários diretamente e são mais adequados para correspondência.Both StringComparison.Ordinal and StringComparison.OrdinalIgnoreCase use the binary values directly, and are best suited for matching. Quando você não tiver certeza sobre as configurações de comparação, use um destes dois valores.When you are not sure about your comparison settings, use one of these two values. No entanto, como elas executam uma comparação byte por byte, elas não classificam por uma ordem de classificação linguística (como um dicionário de inglês), mas por ordem de classificação binária.However, because they perform a byte-by-byte comparison, they do not sort by a linguistic sort order (like an English dictionary) but by a binary sort order. Os resultados podem parecer estranhos na maioria dos contextos se exibido aos usuários.The results may look odd in most contexts if displayed to users.

A semântica ordinal é o padrão para sobrecargas de String.Equals que não incluem um argumento StringComparison (incluindo o operador de igualdade).Ordinal semantics are the default for String.Equals overloads that do not include a StringComparison argument (including the equality operator). Em qualquer caso, é recomendável que você chame uma sobrecarga que tenha um parâmetro StringComparison.In any case, we recommend that you call an overload that has a StringComparison parameter.

Operações da Cadeia de Caracteres que Usam a Cultura InvariávelString Operations that Use the Invariant Culture

As comparações com a cultura invariável usam a propriedade CompareInfo retornada pela propriedade estática CultureInfo.InvariantCulture.Comparisons with the invariant culture use the CompareInfo property returned by the static CultureInfo.InvariantCulture property. Esse comportamento é o mesmo em todos os sistemas, ele converte qualquer caractere fora de seu intervalo no que ele acredita que sejam caracteres invariáveis equivalentes.This behavior is the same on all systems; it translates any characters outside its range into what it believes are equivalent invariant characters. Essa política pode ser útil para manter um conjunto de comportamentos de cadeia de caracteres entre culturas, mas geralmente fornece resultados inesperados.This policy can be useful for maintaining one set of string behavior across cultures, but it often provides unexpected results.

As comparações que não diferenciam maiúsculas de minúsculas com a cultura invariável usam a propriedade CompareInfo estática retornada pela propriedade CultureInfo.InvariantCulture estática para informações de comparação também.Case-insensitive comparisons with the invariant culture use the static CompareInfo property returned by the static CultureInfo.InvariantCulture property for comparison information as well. As diferenças de maiúsculas e minúsculas entre esses caracteres convertidos são ignoradas.Any case differences among these translated characters are ignored.

As comparações que usam StringComparison.InvariantCulture e StringComparison.Ordinal funcionam de forma idêntica em cadeias de caracteres ASCII.Comparisons that use StringComparison.InvariantCulture and StringComparison.Ordinal work identically on ASCII strings. No entanto, StringComparison.InvariantCulture toma decisões linguísticas que podem não ser apropriadas para cadeias de caracteres que devem ser interpretadas como um conjunto de bytes.However, StringComparison.InvariantCulture makes linguistic decisions that might not be appropriate for strings that have to be interpreted as a set of bytes. O objeto CultureInfo.InvariantCulture.CompareInfo faz o método Compare interpretar determinados conjuntos de caracteres como equivalentes.The CultureInfo.InvariantCulture.CompareInfo object makes the Compare method interpret certain sets of characters as equivalent. Por exemplo, a equivalência a seguir é válida na cultura invariável:For example, the following equivalence is valid under the invariant culture:

InvariantCulture: a + ̊ = åInvariantCulture: a + ̊ = å

O caractere de LETRA A MINÚSCULA LATINA "a" (\u0061), quando está próximo ao CARACTERE DE ANEL SUPERIOR COMBINÁVEL "+ " ̊" (\u030a), é interpretado como a LETRA A MINÚSCULA LATINA COM O CARACTERE DE ANEL SUPERIOR "å" (\u00e5).The LATIN SMALL LETTER A character "a" (\u0061), when it is next to the COMBINING RING ABOVE character "+ " ̊" (\u030a), is interpreted as the LATIN SMALL LETTER A WITH RING ABOVE character "å" (\u00e5). Como mostra o exemplo a seguir, esse comportamento é diferente da comparação ordinal.As the following example shows, this behavior differs from ordinal comparison.

string separated = "\u0061\u030a";
string combined = "\u00e5";
      
Console.WriteLine("Equal sort weight of {0} and {1} using InvariantCulture: {2}",
                  separated, combined, 
                  String.Compare(separated, combined, 
                                 StringComparison.InvariantCulture) == 0);

Console.WriteLine("Equal sort weight of {0} and {1} using Ordinal: {2}",
                  separated, combined,
                  String.Compare(separated, combined, 
                                 StringComparison.Ordinal) == 0);
// The example displays the following output:
//    Equal sort weight of a° and å using InvariantCulture: True
//    Equal sort weight of a° and å using Ordinal: False      
Dim separated As String = ChrW(&h61) + ChrW(&h30a)
Dim combined As String = ChrW(&he5)
      
Console.WriteLine("Equal sort weight of {0} and {1} using InvariantCulture: {2}", _
                  separated, combined, _
                  String.Compare(separated, combined, _ 
                                 StringComparison.InvariantCulture) = 0)

Console.WriteLine("Equal sort weight of {0} and {1} using Ordinal: {2}", _
                  separated, combined, _
                  String.Compare(separated, combined, _
                                 StringComparison.Ordinal) = 0)
' The example displays the following output:
'    Equal sort weight of a° and å using InvariantCulture: True
'    Equal sort weight of a° and å using Ordinal: False

Ao interpretar nomes de arquivo, cookies ou qualquer outro elemento em que uma combinação como "å" pode aparecer, as comparações ordinais ainda oferecem o comportamento mais transparente e adequado.When interpreting file names, cookies, or anything else where a combination such as "å" can appear, ordinal comparisons still offer the most transparent and fitting behavior.

De forma geral, a cultura invariável tem muito poucas propriedades que a tornam útil para comparação.On balance, the invariant culture has very few properties that make it useful for comparison. Ela faz a comparação de maneira linguisticamente relevante, o que impede que ela garanta a equivalência simbólica total, mas não é a opção de exibição em nenhuma cultura.It does comparison in a linguistically relevant manner, which prevents it from guaranteeing full symbolic equivalence, but it is not the choice for display in any culture. Um dos motivos para usar StringComparison.InvariantCulture para comparação é persistir dados ordenados, para uma exibição idêntica entre culturas.One of the few reasons to use StringComparison.InvariantCulture for comparison is to persist ordered data for a cross-culturally identical display. Por exemplo, se um arquivo de dados grande que contém uma lista de identificadores classificados para exibição acompanha um aplicativo, a adição a essa lista exige uma inserção com a inserção de estilo invariável.For example, if a large data file that contains a list of sorted identifiers for display accompanies an application, adding to this list would require an insertion with invariant-style sorting.

Voltar ao inícioBack to top

Escolhendo um Membro StringComparison para a Chamada de MétodoChoosing a StringComparison Member for Your Method Call

A tabela a seguir descreve o mapeamento do contexto semântico da cadeia de caracteres para um membro de enumeração StringComparison.The following table outlines the mapping from semantic string context to a StringComparison enumeration member.

DadosData ComportamentoBehavior System.StringComparison correspondenteCorresponding System.StringComparison

Valorvalue
Identificadores internos que diferenciam maiúsculas de minúsculas.Case-sensitive internal identifiers.

Identificadores que diferenciam maiúsculas e minúsculas nos padrões como XML e HTTP.Case-sensitive identifiers in standards such as XML and HTTP.

Configurações relacionadas à segurança que diferenciam maiúsculas de minúsculas.Case-sensitive security-related settings.
Um identificador não linguístico, em que bytes correspondem exatamente.A non-linguistic identifier, where bytes match exactly. Ordinal
Identificadores internos que não diferenciam maiúsculas de minúsculas.Case-insensitive internal identifiers.

Identificadores que não diferenciam maiúsculas e minúsculas em padrões como XML e HTTP.Case-insensitive identifiers in standards such as XML and HTTP.

Caminhos de arquivo.File paths.

Chaves do Registro e valores.Registry keys and values.

Variáveis de ambiente.Environment variables.

Identificadores de recurso (por exemplo, nomes de identificador).Resource identifiers (for example, handle names).

Configurações relacionadas à segurança que não diferenciam maiúsculas de minúsculas.Case-insensitive security-related settings.
Um identificador não linguístico, em que as maiúsculas e minúsculas são irrelevantes; especialmente, dados armazenados na maioria dos serviços de sistema do Windows.A non-linguistic identifier, where case is irrelevant; especially data stored in most Windows system services. OrdinalIgnoreCase
Alguns dados persistentes, linguisticamente relevantes.Some persisted, linguistically relevant data.

Exibição de dados linguísticos que requer uma ordem de classificação fixa.Display of linguistic data that requires a fixed sort order.
Dados independentes de cultura que ainda são linguisticamente relevantes.Culturally agnostic data that still is linguistically relevant. InvariantCulture

- ou --or-

InvariantCultureIgnoreCase
Dados exibidos para o usuário.Data displayed to the user.

A maioria das entradas do usuário.Most user input.
Dados que exigem os costumes linguísticos locais.Data that requires local linguistic customs. CurrentCulture

- ou --or-

CurrentCultureIgnoreCase

Voltar ao inícioBack to top

Métodos comuns de comparação da cadeia de caracteres no .NETCommon String Comparison Methods in .NET

As seções a seguir descrevem os métodos que são mais comumente usados para a comparação de cadeias de caracteres.The following sections describe the methods that are most commonly used for string comparison.

String.CompareString.Compare

Interpretação padrão: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Como a operação mais central da interpretação de cadeia de caracteres, todas as instâncias de chamadas desse método devem ser examinadas para determinar se as cadeias de caracteres devem ser interpretadas de acordo com a cultura atual ou dissociadas da cultura (simbolicamente).As the operation most central to string interpretation, all instances of these method calls should be examined to determine whether strings should be interpreted according to the current culture, or dissociated from the culture (symbolically). Normalmente, é o último e uma comparação StringComparison.Ordinal deve ser usada em vez disso.Typically, it is the latter, and a StringComparison.Ordinal comparison should be used instead.

A classe System.Globalization.CompareInfo, que é retornada pelo CultureInfo.CompareInfo também inclui uma propriedade, um método Compare que fornece um grande número de opções correspondentes (ordinal, ignorando espaço em branco, ignorando tipo kana e assim por diante) por meio da enumeração de sinalizador CompareOptions.The System.Globalization.CompareInfo class, which is returned by the CultureInfo.CompareInfo property, also includes a Compare method that provides a large number of matching options (ordinal, ignoring white space, ignoring kana type, and so on) by means of the CompareOptions flag enumeration.

String.CompareToString.CompareTo

Interpretação padrão: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Esse método no momento não oferece uma sobrecarga que especifica um tipo StringComparison.This method does not currently offer an overload that specifies a StringComparison type. É possível converter esse método para o formulário recomendado String.Compare(String, String, StringComparison).It is usually possible to convert this method to the recommended String.Compare(String, String, StringComparison) form.

Os tipos que implementam as interfaces IComparable e IComparable<T> implementam este método.Types that implement the IComparable and IComparable<T> interfaces implement this method. Como ele não oferece a opção de um parâmetro StringComparison, os tipos de implementação geralmente permitem que o usuário especifique um StringComparer em seu construtor.Because it does not offer the option of a StringComparison parameter, implementing types often let the user specify a StringComparer in their constructor. O exemplo a seguir define uma classe FileName cujo construtor de classe inclui um parâmetro StringComparer.The following example defines a FileName class whose class constructor includes a StringComparer parameter. Esse objeto StringComparer é usado no método FileName.CompareTo.This StringComparer object is then used in the FileName.CompareTo method.

using System;

public class FileName : IComparable
{
   string fname;
   StringComparer comparer; 
   
   public FileName(string name, StringComparer comparer)
   {
      if (String.IsNullOrEmpty(name))
         throw new ArgumentNullException("name");

      this.fname = name;
      
      if (comparer != null)
         this.comparer = comparer;
      else
         this.comparer = StringComparer.OrdinalIgnoreCase;
   }

   public string Name
   {
      get { return fname; }
   }
   
   public int CompareTo(object obj)
   {
      if (obj == null) return 1;

      if (! (obj is FileName))
         return comparer.Compare(this.fname, obj.ToString());
      else
         return comparer.Compare(this.fname, ((FileName) obj).Name);
   }
}
Public Class FileName : Implements IComparable
   Dim fname As String
   Dim comparer As StringComparer 
   
   Public Sub New(name As String, comparer As StringComparer)
      If String.IsNullOrEmpty(name) Then
         Throw New ArgumentNullException("name")
      End If

      Me.fname = name
      
      If comparer IsNot Nothing Then
         Me.comparer = comparer
      Else
         Me.comparer = StringComparer.OrdinalIgnoreCase
      End If      
   End Sub

   Public ReadOnly Property Name As String
      Get
         Return fname
      End Get   
   End Property
   
   Public Function CompareTo(obj As Object) As Integer _
          Implements IComparable.CompareTo
      If obj Is Nothing Then Return 1

      If Not TypeOf obj Is FileName Then
         obj = obj.ToString()
      Else
         obj = CType(obj, FileName).Name
      End If         
      Return comparer.Compare(Me.fname, obj)
   End Function
End Class

String.EqualsString.Equals

Interpretação padrão: StringComparison.Ordinal.Default interpretation: StringComparison.Ordinal.

A classe String permite que você teste a igualdade chamando as sobrecargas do método Equals ou estáticas ou usando o operador de igualdade estático.The String class lets you test for equality by calling either the static or instance Equals method overloads, or by using the static equality operator. O operador e as sobrecargas utilizam a comparação ordinal por padrão.The overloads and operator use ordinal comparison by default. No entanto, ainda é recomendável que você chame uma sobrecarga que especifique explicitamente o tipo StringComparison mesmo se você desejar executar uma comparação ordinal. Isso facilita a pesquisa de código para uma determinada interpretação da cadeia de caracteres.However, we still recommend that you call an overload that explicitly specifies the StringComparison type even if you want to perform an ordinal comparison; this makes it easier to search code for a certain string interpretation.

String.ToUpper e String.ToLowerString.ToUpper and String.ToLower

Interpretação padrão: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Você deve ter cuidado ao usar esses métodos, pois forçar uma cadeia de caracteres para maiúsculas ou minúsculas normalmente é usado como uma normalização pequena para comparar cadeias de caracteres independentemente de maiúsculas e minúsculas.You should be careful when you use these methods, because forcing a string to a uppercase or lowercase is often used as a small normalization for comparing strings regardless of case. Nesse caso, considere o uso de uma comparação que não diferencie maiúsculas de minúsculas.If so, consider using a case-insensitive comparison.

Os métodos String.ToUpperInvariant e String.ToLowerInvariant também estão disponíveis.The String.ToUpperInvariant and String.ToLowerInvariant methods are also available. ToUpperInvariant é o modo padrão para normalizar maiúsculas e minúsculas.ToUpperInvariant is the standard way to normalize case. As comparações feitas usando StringComparison.OrdinalIgnoreCase são a composição de duas chamadas de maneira comportamental: chamar ToUpperInvariant em ambos os argumentos de cadeia de caracteres e fazer uma comparação usando StringComparison.Ordinal.Comparisons made using StringComparison.OrdinalIgnoreCase are behaviorally the composition of two calls: calling ToUpperInvariant on both string arguments, and doing a comparison using StringComparison.Ordinal.

Também há sobrecargas disponíveis para converter para maiúsculas e minúsculas em uma cultura específica, passando um objeto CultureInfo que representa aquela cultura para o método.Overloads are also available for converting to uppercase and lowercase in a specific culture, by passing a CultureInfo object that represents that culture to the method.

Char.ToUpper e Char.ToLowerChar.ToUpper and Char.ToLower

Interpretação padrão: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Esses métodos funcionam da mesma forma que os métodos String.ToUpper e String.ToLower descritos na seção anterior.These methods work similarly to the String.ToUpper and String.ToLower methods described in the previous section.

String.StartsWith e String.EndsWithString.StartsWith and String.EndsWith

Interpretação padrão: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Por padrão, esses dois métodos executam uma comparação que leva em conta a cultura.By default, both of these methods perform a culture-sensitive comparison.

String.IndexOf e String.LastIndexOfString.IndexOf and String.LastIndexOf

Interpretação padrão: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Há uma falta de consistência em como as sobrecargas padrão desses métodos realizam comparações.There is a lack of consistency in how the default overloads of these methods perform comparisons. Todos os métodos String.IndexOf e String.LastIndexOf que incluem um parâmetro Char realizam uma comparação ordinal, mas os métodos padrão String.IndexOf e String.LastIndexOf que incluem um parâmetro String executam uma comparação que diferencia a cultura.All String.IndexOf and String.LastIndexOf methods that include a Char parameter perform an ordinal comparison, but the default String.IndexOf and String.LastIndexOf methods that include a String parameter perform a culture-sensitive comparison.

Se você chamar o método String.IndexOf(String) ou String.LastIndexOf(String) e passar a ele uma cadeia de caracteres para localizar na instância atual, é recomendável que você chame uma sobrecarga que especifique explicitamente o tipo StringComparison.If you call the String.IndexOf(String) or String.LastIndexOf(String) method and pass it a string to locate in the current instance, we recommend that you call an overload that explicitly specifies the StringComparison type. As sobrecargas que incluem um argumento Char não permitem que você especifique um tipo StringComparison.The overloads that include a Char argument do not allow you to specify a StringComparison type.

Voltar ao inícioBack to top

Métodos que Realizam Comparação da Cadeia de Caracteres IndiretamenteMethods that Perform String Comparison Indirectly

Alguns métodos que não de cadeias de caracteres que têm a comparação de cadeia de caracteres como uma operação central usam o tipo StringComparer.Some non-string methods that have string comparison as a central operation use the StringComparer type. A classe StringComparer inclui quatro propriedades estáticas que retornam instâncias StringComparer cujos métodos StringComparer.Compare realizam os seguintes tipos de comparações de cadeias de caracteres:The StringComparer class includes six static properties that return StringComparer instances whose StringComparer.Compare methods perform the following types of string comparisons:

Array.Sort e Array.BinarySearchArray.Sort and Array.BinarySearch

Interpretação padrão: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Ao armazenar quaisquer dados em uma coleção ou ler dados persistentes de um arquivo ou banco de dados em uma coleção, alternar a cultura atual pode invalidar as invariáveis na coleção.When you store any data in a collection, or read persisted data from a file or database into a collection, switching the current culture can invalidate the invariants in the collection. O método Array.BinarySearch presume que os elementos na matriz a serem pesquisados já estão classificados.The Array.BinarySearch method assumes that the elements in the array to be searched are already sorted. Para classificar qualquer elemento de cadeia de caracteres na matriz, o método Array.Sort chama o método String.Compare para ordenar os elementos individuais.To sort any string element in the array, the Array.Sort method calls the String.Compare method to order individual elements. Usar um comparador que leva em conta a cultura pode ser perigoso se a cultura mudar entre o momento em que a matriz é ordenada e que seu conteúdo é pesquisado.Using a culture-sensitive comparer can be dangerous if the culture changes between the time that the array is sorted and its contents are searched. Por exemplo, no código a seguir, o armazenamento e a recuperação operam no comparador que é fornecido implicitamente pela propriedade Thread.CurrentThread.CurrentCulture.For example, in the following code, storage and retrieval operate on the comparer that is provided implicitly by the Thread.CurrentThread.CurrentCulture property. Se a cultura puder mudar entre as chamadas para StoreNames e DoesNameExist, e especialmente se os conteúdos da matriz forem mantidos em algum lugar entre as duas chamadas de método, a pesquisa binária poderá falhar.If the culture can change between the calls to StoreNames and DoesNameExist, and especially if the array contents are persisted somewhere between the two method calls, the binary search may fail.

// Incorrect.
string []storedNames;

public void StoreNames(string [] names)
{
   int index = 0;
   storedNames = new string[names.Length];

   foreach (string name in names)
   {
      this.storedNames[index++] = name;
   }

   Array.Sort(names); // Line A.
}

public bool DoesNameExist(string name)
{
   return (Array.BinarySearch(this.storedNames, name) >= 0);  // Line B.
}
' Incorrect.
Dim storedNames() As String

Public Sub StoreNames(names() As String)
   Dim index As Integer = 0
   ReDim storedNames(names.Length - 1)
   
   For Each name As String In names
      Me.storedNames(index) = name
      index+= 1
   Next
   
   Array.Sort(names)          ' Line A.
End Sub

Public Function DoesNameExist(name As String) As Boolean
   Return Array.BinarySearch(Me.storedNames, name) >= 0      ' Line B.
End Function

Uma variação recomendada é exibida no exemplo a seguir, que usa o mesmo método de comparação (que não leva em conta a cultura) ordinal para classificar e pesquisar a matriz.A recommended variation appears in the following example, which uses the same ordinal (culture-insensitive) comparison method both to sort and to search the array. O código de alteração é refletido nas linhas rotuladas como Line A e Line B nos dois exemplos.The change code is reflected in the lines labeled Line A and Line B in the two examples.

// Correct.
string []storedNames;

public void StoreNames(string [] names)
{
   int index = 0;
   storedNames = new string[names.Length];

   foreach (string name in names)
   {
      this.storedNames[index++] = name;
   }

   Array.Sort(names, StringComparer.Ordinal);  // Line A.
}

public bool DoesNameExist(string name)
{
   return (Array.BinarySearch(this.storedNames, name, StringComparer.Ordinal) >= 0);  // Line B.
}
' Correct.
Dim storedNames() As String

Public Sub StoreNames(names() As String)
   Dim index As Integer = 0
   ReDim storedNames(names.Length - 1)
   
   For Each name As String In names
      Me.storedNames(index) = name
      index+= 1
   Next
   
   Array.Sort(names, StringComparer.Ordinal)           ' Line A.
End Sub

Public Function DoesNameExist(name As String) As Boolean
   Return Array.BinarySearch(Me.storedNames, name, StringComparer.Ordinal) >= 0      ' Line B.
End Function

Se esses dados forem mantidos e movidos entre as culturas e a classificação for usada para apresentar esses dados para o usuário, você pode considerar usar StringComparison.InvariantCulture, que opera linguisticamente para a melhor saída do usuário, mas não é afetado pelas alterações na cultura.If this data is persisted and moved across cultures, and sorting is used to present this data to the user, you might consider using StringComparison.InvariantCulture, which operates linguistically for better user output but is unaffected by changes in culture. O exemplo a seguir modifica os dois exemplos anteriores para usar a cultura invariável para classificar e pesquisar a matriz.The following example modifies the two previous examples to use the invariant culture for sorting and searching the array.

// Correct.
string []storedNames;

public void StoreNames(string [] names)
{
   int index = 0;
   storedNames = new string[names.Length];

   foreach (string name in names)
   {
      this.storedNames[index++] = name;
   }

   Array.Sort(names, StringComparer.InvariantCulture);  // Line A.
}

public bool DoesNameExist(string name)
{
   return (Array.BinarySearch(this.storedNames, name, StringComparer.InvariantCulture) >= 0);  // Line B.
}
' Correct.
Dim storedNames() As String

Public Sub StoreNames(names() As String)
   Dim index As Integer = 0
   ReDim storedNames(names.Length - 1)
   
   For Each name As String In names
      Me.storedNames(index) = name
      index+= 1
   Next
   
   Array.Sort(names, StringComparer.InvariantCulture)           ' Line A.
End Sub

Public Function DoesNameExist(name As String) As Boolean
   Return Array.BinarySearch(Me.storedNames, name, StringComparer.InvariantCulture) >= 0      ' Line B.
End Function

Exemplo de Coleções: Construtor de Tabela de HashCollections Example: Hashtable Constructor

As cadeias de caracteres de hash fornecem um segundo exemplo de uma operação que é afetada pela maneira como as cadeias de caracteres são comparadas.Hashing strings provides a second example of an operation that is affected by the way in which strings are compared.

O exemplo a seguir cria um objeto Hashtable passando-o para o objeto StringComparer que é retornado pela propriedade StringComparer.OrdinalIgnoreCase.The following example instantiates a Hashtable object by passing it the StringComparer object that is returned by the StringComparer.OrdinalIgnoreCase property. Como uma classe StringComparer que é derivada de StringComparer implementa a interface IEqualityComparer, seu método GetHashCode é usado para calcular o código hash de cadeias de caracteres na tabela de hash.Because a class StringComparer that is derived from StringComparer implements the IEqualityComparer interface, its GetHashCode method is used to compute the hash code of strings in the hash table.

const int initialTableCapacity = 100;
Hashtable h;

public void PopulateFileTable(string directory)
{
   h = new Hashtable(initialTableCapacity, 
                     StringComparer.OrdinalIgnoreCase);
         
   foreach (string file in Directory.GetFiles(directory))
         h.Add(file, File.GetCreationTime(file));
}

public void PrintCreationTime(string targetFile)
{
   Object dt = h[targetFile];
   if (dt != null)
   {
      Console.WriteLine("File {0} was created at time {1}.",
         targetFile, 
         (DateTime) dt);
   }
   else
   {
      Console.WriteLine("File {0} does not exist.", targetFile);
   }
}
Const initialTableCapacity As Integer = 100
Dim h As Hashtable

Public Sub PopulateFileTable(dir As String)
   h = New Hashtable(initialTableCapacity, _
                     StringComparer.OrdinalIgnoreCase)
                     
   For Each filename As String In Directory.GetFiles(dir)
      h.Add(filename, File.GetCreationTime(filename))
   Next                        
End Sub

Public Sub PrintCreationTime(targetFile As String)
   Dim dt As Object = h(targetFile)
   If dt IsNot Nothing Then
      Console.WriteLine("File {0} was created at {1}.", _
         targetFile, _
         CDate(dt))
   Else
      Console.WriteLine("File {0} does not exist.", targetFile)
   End If
End Sub  

Voltar ao inícioBack to top

Exibindo e Mantendo Dados FormatadosDisplaying and Persisting Formatted Data

Quando você exibir dados que não são de cadeias de caracteres como números e datas e horas para os usuários, formate-os usando as configurações culturais do usuário.When you display non-string data such as numbers and dates and times to users, format them by using the user's cultural settings. Por padrão, todos itens a seguir usam a cultura do thread atual em operações de formatação:By default, the following all use the current thread culture in formatting operations:

  • Cadeias de caracteres interpoladas compatíveis com os compiladores C# e Visual Basic.Interpolated strings supported by the C# and Visual Basic compilers.

  • Operações de concatenação de cadeias de caracteres que usam os operadores de concatenação do C# ou Visual Basic, ou que chamam o método String.Concat diretamente.String concatenation operations that use the C# or Visual Basic concatenation operators or that call the String.Concat method directly.

  • O método String.Format.The String.Format method.

  • Os métodos ToString dos tipos numéricos e dos tipos de data e hora.The ToString methods of the numeric types and the date and time types.

Para especificar explicitamente que uma cadeia de caracteres deve ser formatada usando as convenções de uma cultura específica ou a cultura invariável, você pode fazer o seguinte:To explicitly specify that a string should be formatted by using the conventions of a designated culture or the invariant culture, you can do the following:

  • Ao usar os métodos String.Format e ToString, chame uma sobrecarga que tenha um parâmetro provider, tal como String.Format(IFormatProvider, String, Object[]) ou DateTime.ToString(IFormatProvider), e passe a ela a propriedade CultureInfo.CurrentCulture, a propriedade CultureInfo.InvariantCulture ou uma instância de CultureInfo que represente a cultura desejada.When using the String.Format and ToString methods, call an overload that has a provider parameter, such as String.Format(IFormatProvider, String, Object[]) or DateTime.ToString(IFormatProvider), and pass it the CultureInfo.CurrentCulture property, a CultureInfo instance that represents the desired culture, or the CultureInfo.InvariantCulture property.

  • Para concatenação de cadeias de caracteres, não permita que o compilador execute nenhuma conversão implícita.For string concatenation, do not allow the compiler to perform any implicit conversions. Em vez disso, execute uma conversão explícita, chamando uma sobrecarga ToString que tenha um parâmetro provider.Instead, perform an explicit conversion by calling a ToString overload that has a provider parameter. Por exemplo, o compilador usa implicitamente a cultura atual ao converter um valor de Double em uma cadeia de caracteres no código C# a seguir:For example, the compiler implicitly uses the current culture when converting a Double value to a string in the following C# code:

    string concat1 = "The amount is " + 126.03 + ".";
    Console.WriteLine(concat1);
    

    Em vez disso, você pode especificar explicitamente a cultura cujas convenções de formatação são usadas na conversão ao chamar o método Double.ToString(IFormatProvider), assim como o código C# a seguir faz:Instead, you can explicitly specify the culture whose formatting conventions are used in the conversion by calling the Double.ToString(IFormatProvider) method, as the following C# code does:

    string concat2 = "The amount is " + 126.03.ToString(CultureInfo.InvariantCulture) + ".";
    Console.WriteLine(concat2);
    
  • Para a interpolação de cadeia de caracteres, em vez de atribuir uma cadeia de caracteres interpolada a uma instância de String, atribua-a a um FormattableString.For string interpolation, rather than assigning an interpolated string to a String instance, assign it to a FormattableString. Em seguida, você pode chamar o respectivo método FormattableString.ToString() para produzir uma cadeia de caracteres de resultado que reflete as convenções da cultura atual, ou então pode chamar o método FormattableString.ToString(IFormatProvider) para produzir uma cadeia de caracteres de resultado que reflete as convenções de uma cultura específica.You can then call its FormattableString.ToString() method produce a result string that reflects the conventions of the current culture, or you can call the FormattableString.ToString(IFormatProvider) method to produce a result string that reflects the conventions of a specified culture. Você também pode passar a cadeia de caracteres formatável para o método FormattableString.Invariant estático para produzir uma cadeia de caracteres de resultado que reflete as convenções da cultura invariável.You can also pass the formattable string to the static FormattableString.Invariant method to produce a result string that reflects the conventions of the invariant culture. O exemplo a seguir ilustra esta abordagem.The following example illustrates this approach. (A saída do exemplo reflete uma cultura atual de en-US.)(The output from the example reflects a current culture of en-US.)

    using System;
    using System.Globalization;
    
    class Program
    {
        static void Main()
        {
            Decimal value = 126.03m;
            FormattableString amount = $"The amount is {value:C}"; 
            Console.WriteLine(amount.ToString());
            Console.WriteLine(amount.ToString(new CultureInfo("fr-FR")));
            Console.WriteLine(FormattableString.Invariant(amount));
        }
    }
    // The example displays the following output:
    //    The amount is $126.03
    //    The amount is 126,03 €
    //    The amount is ¤126.03
    
    Imports System.Globalization
    
    Module Program
        Sub Main()
            Dim value As Decimal = 126.03
            Dim amount As FormattableString = $"The amount is {value:C}" 
            Console.WriteLine(amount.ToString())
            Console.WriteLine(amount.ToString(new CultureInfo("fr-FR")))
            Console.WriteLine(FormattableString.Invariant(amount))
        End Sub
    End Module
    ' The example displays the following output:
    '    The amount is $126.03
    '    The amount is 126,03 €
    '    The amount is ¤126.03
    

Você pode manter os dados que não são de cadeias de caracteres como dados binários ou como dados formatados.You can persist non-string data either as binary data or as formatted data. Se optar por salvá-los como dados formatados, você deverá chamar uma sobrecarga de método de formatação que inclua um parâmetro provider e passar para ele a propriedade CultureInfo.InvariantCulture.If you choose to save it as formatted data, you should call a formatting method overload that includes a provider parameter and pass it the CultureInfo.InvariantCulture property. A cultura invariável fornece um formato consistente para os dados formatados que é independente da cultura e do computador.The invariant culture provides a consistent format for formatted data that is independent of culture and machine. Em contraste, dados persistentes que são formatados usando culturas diferentes da cultura invariável têm várias limitações:In contrast, persisting data that is formatted by using cultures other than the invariant culture has a number of limitations:

  • É provável que os dados não sejam utilizáveis se forem recuperados em um sistema que tem uma cultura diferente ou se o usuário do sistema atual alterar a cultura atual e tentar recuperar os dados.The data is likely to be unusable if it is retrieved on a system that has a different culture, or if the user of the current system changes the current culture and tries to retrieve the data.

  • As propriedades de uma cultura em um computador específico podem ser diferentes dos valores padrão.The properties of a culture on a specific computer can differ from standard values. A qualquer momento, um usuário pode personalizar as configurações de exibição que levam em conta a cultura.At any time, a user can customize culture-sensitive display settings. Devido a isso, os dados formatados que são salvos em um sistema podem não ser legíveis após o usuário personalizar as configurações culturais.Because of this, formatted data that is saved on a system may not be readable after the user customizes cultural settings. É provável que a portabilidade dos dados formatados entre computadores seja ainda mais limitada.The portability of formatted data across computers is likely to be even more limited.

  • Os padrões internacionais, regionais ou nacionais que controlam a formatação de números ou datas e horas são alterados ao longo do tempo e essas alterações são incorporadas nas atualizações do sistema operacional Windows.International, regional, or national standards that govern the formatting of numbers or dates and times change over time, and these changes are incorporated into Windows operating system updates. Quando as convenções de formatação mudam, os dados que foram formatados usando as convenções anteriores podem se tornar ilegíveis.When formatting conventions change, data that was formatted by using the previous conventions may become unreadable.

O exemplo a seguir ilustra a portabilidade limitada resultante do uso da formatação que leva em conta a cultura para manter os dados.The following example illustrates the limited portability that results from using culture-sensitive formatting to persist data. O exemplo salva uma matriz de valores de data e hora em um arquivo.The example saves an array of date and time values to a file. Eles são formatados usando as convenções da cultura do inglês (Estados Unidos).These are formatted by using the conventions of the English (United States) culture. Depois que o aplicativo altera a cultura do thread atual para francês (Suíça), ele tenta ler os valores salvos usando as convenções de formatação da cultura atual.After the application changes the current thread culture to French (Switzerland), it tries to read the saved values by using the formatting conventions of the current culture. A tentativa de ler dois dos itens de dados gera uma exceção FormatException e a matriz de datas agora contém dois elementos incorretos que são iguais a MinValue.The attempt to read two of the data items throws a FormatException exception, and the array of dates now contains two incorrect elements that are equal to MinValue.

using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading;

public class Example
{
   private static string filename = @".\dates.dat";

   public static void Main()
   {
      DateTime[] dates = { new DateTime(1758, 5, 6, 21, 26, 0), 
                           new DateTime(1818, 5, 5, 7, 19, 0), 
                           new DateTime(1870, 4, 22, 23, 54, 0),  
                           new DateTime(1890, 9, 8, 6, 47, 0), 
                           new DateTime(1905, 2, 18, 15, 12, 0) }; 
      // Write the data to a file using the current culture.
      WriteData(dates);
      // Change the current culture.
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-CH");
      // Read the data using the current culture.
      DateTime[] newDates = ReadData();
      foreach (var newDate in newDates)
         Console.WriteLine(newDate.ToString("g"));
   }
   
   private static void WriteData(DateTime[] dates) 
   {
      StreamWriter sw = new StreamWriter(filename, false, Encoding.UTF8);    
      for (int ctr = 0; ctr < dates.Length; ctr++) {
         sw.Write("{0}", dates[ctr].ToString("g", CultureInfo.CurrentCulture));
         if (ctr < dates.Length - 1) sw.Write("|");   
      }      
      sw.Close();
   }
   
   private static DateTime[] ReadData() 
   {
      bool exceptionOccurred = false;
           
      // Read file contents as a single string, then split it.
      StreamReader sr = new StreamReader(filename, Encoding.UTF8);
      string output = sr.ReadToEnd();
      sr.Close();   

      string[] values = output.Split( new char[] { '|' } );
      DateTime[] newDates = new DateTime[values.Length]; 
      for (int ctr = 0; ctr < values.Length; ctr++) {
         try {
            newDates[ctr] = DateTime.Parse(values[ctr], CultureInfo.CurrentCulture);
         }
         catch (FormatException) {
            Console.WriteLine("Failed to parse {0}", values[ctr]);
            exceptionOccurred = true;
         }
      }      
      if (exceptionOccurred) Console.WriteLine();
      return newDates;
   }
}
// The example displays the following output:
//       Failed to parse 4/22/1870 11:54 PM
//       Failed to parse 2/18/1905 3:12 PM
//       
//       05.06.1758 21:26
//       05.05.1818 07:19
//       01.01.0001 00:00
//       09.08.1890 06:47
//       01.01.0001 00:00
//       01.01.0001 00:00
Imports System.Globalization
Imports System.IO
Imports System.Text
Imports System.Threading

Module Example
   Private filename As String = ".\dates.dat"
   
   Public Sub Main()
      Dim dates() As Date = { #5/6/1758 9:26PM#, #5/5/1818 7:19AM#, _ 
                              #4/22/1870 11:54PM#, #9/8/1890 6:47AM#, _ 
                              #2/18/1905 3:12PM# }
      ' Write the data to a file using the current culture.
      WriteData(dates)
      ' Change the current culture.
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-CH")
      ' Read the data using the current culture.
      Dim newDates() As Date = ReadData()
      For Each newDate In newDates
         Console.WriteLine(newDate.ToString("g"))
      Next
   End Sub
   
   Private Sub WriteData(dates() As Date)
      Dim sw As New StreamWriter(filename, False, Encoding.Utf8)    
      For ctr As Integer = 0 To dates.Length - 1
         sw.Write("{0}", dates(ctr).ToString("g", CultureInfo.CurrentCulture))
         If ctr < dates.Length - 1 Then sw.Write("|")   
      Next      
      sw.Close()
   End Sub
   
   Private Function ReadData() As Date()
      Dim exceptionOccurred As Boolean = False
           
      ' Read file contents as a single string, then split it.
      Dim sr As New StreamReader(filename, Encoding.Utf8)
      Dim output As String = sr.ReadToEnd()
      sr.Close()   

      Dim values() As String = output.Split( {"|"c } )
      Dim newDates(values.Length - 1) As Date 
      For ctr As Integer = 0 To values.Length - 1
         Try
            newDates(ctr) = DateTime.Parse(values(ctr), CultureInfo.CurrentCulture)
         Catch e As FormatException
            Console.WriteLine("Failed to parse {0}", values(ctr))
            exceptionOccurred = True
         End Try
      Next      
      If exceptionOccurred Then Console.WriteLine()
      Return newDates
   End Function
End Module
' The example displays the following output:
'       Failed to parse 4/22/1870 11:54 PM
'       Failed to parse 2/18/1905 3:12 PM
'       
'       05.06.1758 21:26
'       05.05.1818 07:19
'       01.01.0001 00:00
'       09.08.1890 06:47
'       01.01.0001 00:00
'       01.01.0001 00:00
'

No entanto, se você substituir a propriedade CultureInfo.CurrentCulture por CultureInfo.InvariantCulture em chamadas para DateTime.ToString(String, IFormatProvider) e DateTime.Parse(String, IFormatProvider), os dados persistentes de data e hora serão restaurados com êxito, como mostra a saída a seguir.However, if you replace the CultureInfo.CurrentCulture property with CultureInfo.InvariantCulture in the calls to DateTime.ToString(String, IFormatProvider) and DateTime.Parse(String, IFormatProvider), the persisted date and time data is successfully restored, as the following output shows.

06.05.1758 21:26  
05.05.1818 07:19  
22.04.1870 23:54  
08.09.1890 06:47  
18.02.1905 15:12  

Consulte tambémSee also