Existe um operador igual a maiúsculas e minúsculas em C #?

156

Eu sei que o seguinte diferencia maiúsculas de minúsculas:

if (StringA == StringB) {

Então, existe um operador que compare duas strings de maneira insensível?

GateKiller
fonte
possível duplicata de Caselessly comparando strings em C #
Nawfal
No caso de alguém se depara com esta questão procurando uma comparação insensível caso para um Dictionary <string, int>, ter um olhar para esta questão aqui: Caso acesso insensível para dicionário genérico
Robotnik
Seria muito legal; diga para definir um correspondente ~=para paralelo ==como uma versão que não diferencia maiúsculas de minúsculas.
eidylon
Se os desenvolvedores da Microsoft perceberem isso, acho que é necessário um operador que não diferencie maiúsculas de minúsculas na próxima versão do csharp. Essa string.Equal () é longa.
Rez.Net

Respostas:

288

Tente o seguinte:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
John Feminella
fonte
Sou um novato no StackOverflow - você pode explicar o que quer dizer com adição de um link? Você quer dizer os documentos do MSDN?
31119 John Feminella
55
Se você deseja uma comparação sensível à cultura, use este método. Se você quiser apenas garantir que "FILE" e "arquivo" sejam aceitos, use "OrdinalIgnoreCase" ou seu código poderá não funcionar em locais como locais turcos. Para mais informações, consulte moserware.com/2008/02/does-your-code-pass-turkey-test.html
Jeff Moser
10
Não tenho certeza do que Samuel está falando ... essa resposta é perfeita. É correto e auto-explicativo. Não precisa de referências. +1
Sailing Judo
3
Argh, isso é um bocado horrível! meu teclado vai se desgastar. Longe vão os dias em que eu posso usar " if A$=B$ then goto 10"
Sanjay Manohar
9
@Sanjay Manohar Em seguida, escreva um operador personalizado - e eu recomendaria um teclado melhor.
Rushyo 13/08/12
37

A melhor maneira de comparar duas cadeias de caracteres ignorando as letras maiúsculas e minúsculas é usar o método estático String.Equals , especificando uma comparação ordinal de letras de maiúsculas e minúsculas . Essa também é a maneira mais rápida, muito mais rápida do que converter as seqüências para minúsculas ou maiúsculas e compará-las depois disso.

Testei o desempenho de ambas as abordagens e a comparação ordinal da cadeia de caracteres ignorar maiúsculas e minúsculas foi 9 vezes mais rápida ! Também é mais confiável do que converter seqüências de caracteres para maiúsculas ou minúsculas (confira o problema do i turco). Portanto, sempre use o método String.Equals para comparar seqüências de caracteres para igualdade:

String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);

Se você deseja executar uma comparação de cadeias específicas da cultura, pode usar o seguinte código:

String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);

Observe que o segundo exemplo usa a lógica de comparação de strings da cultura atual, o que o torna mais lento que a comparação "caso de ignição ordinal" no primeiro exemplo, portanto, se você não precisar de nenhuma lógica de comparação de strings específica da cultura e estiver após o desempenho máximo, use a comparação "ignorar caso ordinal".

Para mais informações, leia a história completa no meu blog .

Pavel Vladov
fonte
1
Não sugira ToLowerou ToLowerInvariant: eles criam memória apenas para realizar uma comparação e podem falhar à medida que novos conjuntos de caracteres são adicionados ao unicode. ToUpperfalha por causa do turco 'i', entre outros; não há razão para ToLowerque não falhe no futuro por razões semelhantes.
Antiduh 15/05
@antiduh, obrigado pelo seu comentário. Muitos de nós estamos cientes desses problemas em potencial, muitos tutoriais pela Internet dão o 'i' turco como exemplo. Como você pode ver no meu post, eu não recomendo o uso ToLowerou ToLowerInvariantmétodos, eu só queria mostrar o quanto mais eficiente o String.Equalsmétodo é.
Pavel Vladov
3
"Muitos de nós estamos cientes desses problemas em potencial, muitos tutoriais pela Internet dão o 'i' turco como exemplo" - não há pessoas suficientes e você ainda o menciona como a segunda frase da sua resposta. Além disso, sua resposta não inclui justificativa suficiente para nunca usá-la - você simplesmente menciona desempenho; o desempenho nem sempre é a prioridade final. Como resultado, você está violando as diretrizes da Central de Ajuda. os links para sites externos são bons, mas você não resumiu o conteúdo suficientemente (problema 'i' em turco). SO não é sua plataforma de publicidade.
Antiduh 18/05
20

Existem várias propriedades na StringComparerclasse estática que retornam comparadores para qualquer tipo de distinção entre maiúsculas e minúsculas que você queira:

StringComparer Propriedades

Por exemplo, você pode ligar

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

ou

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

É um pouco mais limpo do que os string.Equalsou string.Comparesobrecargas que levam um StringComparisonargumento.

Ryan Lundy
fonte
15
System.Collections.CaseInsensitiveComparer

ou

System.StringComparer.OrdinalIgnoreCase
leppie
fonte
Isso afeta todo o aplicativo?
10339 GateKiller
3
Onde posso encontrar mais informações sobre isso. Isso significa que posso usar == para uma correspondência que não diferencia maiúsculas de minúsculas?
GateKiller 10/03/09
9
string.Equals(StringA, StringB, StringComparison.CurrentCultureIgnoreCase);
Erick
fonte
8

ou

if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {

mas você precisa ter certeza de que StringA não é nulo. Então provavelmente é melhor usar:

string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);

como John sugeriu

EDIT: corrigido o erro

Grzenio
fonte
4

Você pode usar

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))
Andy Mikula
fonte
3

Operador? NÃO, mas acho que você pode mudar sua cultura para que a comparação de cadeias não faça distinção entre maiúsculas e minúsculas.

// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo

Estou confiante de que isso mudará a maneira como as strings estão sendo comparadas pelo operador igual.

John Leidegren
fonte
Sim, para dizer o mínimo, não é exatamente o que você gostaria de fazer, a menos que você queira que todas as comparações de strings não diferenciam maiúsculas de minúsculas. Mas acho que muda o comportamento do operador igual.
John Leidegren
3

Aqui está uma idéia para simplificar a sintaxe:

public class IgnoreCase
{
    private readonly string _value;

    public IgnoreCase(string s)
    {
        _value = s;
    }

    protected bool Equals(IgnoreCase other)
    {
        return this == other;
    }

    public override bool Equals(object obj)
    {
        return obj != null &&
               (ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
    }

    public override int GetHashCode()
    {
        return _value?.GetHashCode() ?? 0;
    }

    public static bool operator ==(IgnoreCase a, IgnoreCase b)
    {
        return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
    }

    public static bool operator !=(IgnoreCase a, IgnoreCase b)
    {
        return !(a == b);
    }

    public static implicit operator string(IgnoreCase s)
    {
        return s._value;
    }

    public static implicit operator IgnoreCase(string s)
    {
        return new IgnoreCase(s);
    }
}

Utilizável como:

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true
renouve
fonte
Embora eu goste da sintaxe de uso com aparência limpa , ela é um pouco enganadora ( IgnoreCasevs IgnoreCaseString) e ambígua (Java escolhe unboxing implícito vs box implícito, então acredito que isso não funcionaria em Java com o implícito convertido de volta para a cadeia de caracteres). E isso cria a sobrecarga de memória de 2 novos objetos com a execução da árvore de chamadas para cada comparação, saltando para várias chamadas de método aninhadas para o caso de uso exibido. Dito isto, na maioria dos casos, o desempenho provavelmente é bom o suficiente.
Arkaine55
Embora essa seja uma idéia inteligente , não é realmente sábia do ponto de vista de manutenção. Você está efetivamente criando um tipo de string substituto em vez de usar o tipo de string interno do sistema. O programador que vier depois não entenderá o que está acontecendo de relance e então ele / ela xingará você. Usar string.Equals () não é tão ruim assim e a maioria das pessoas entenderá o que está fazendo.
ntcolonel
1

Estou tão acostumado a digitar no final desses métodos de comparação: , StringComparison.

Então eu fiz uma extensão.

namespace System
{   public static class StringExtension
    {
        public static bool Equals(this string thisString, string compareString,
             StringComparison stringComparison)
        {
            return string.Equals(thisString, compareString, stringComparison);
        }
    }
}

Observe que você precisará verificar se há nulo thisStringantes de chamar o ext.

Valamas
fonte
1
É o mesmo que este método interno nas versões atuais do .NET Framework? docs.microsoft.com/en-gb/dotnet/api/…
Bernard Vander Beken
1
Parece que sim. Parece que as versões posteriores do .net incluem isso agora.
Valamas 27/03
Disponível desde o .NET 4.5 e todas as versões do .NET Core.
Bernard Vander Beken /
0
string.Compare(string1, string2, true)
user25623
fonte
0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

As pessoas relatam que ToUpperInvariant () é mais rápido que ToLowerInvariant ().

knoopx
fonte
1
Invariante pode ser uma má ideia se a cultura atual ou desejada tiver regras especiais para maiúsculas e minúsculas.
OregonGhost 10/03/09
Isso cria uma nova cópia de cada sequência? Se assim for, má ideia.
Cjk 10/03/09
1
Isso também emitirá uma exceção se uma (ou ambas) as strings forem nulas.
tvanfosson
3
Em termos de desempenho, essa não é uma solução tão boa, pois você também criará duas novas instâncias de string aqui.
Frederik Gheysels 13/03/09
0

Outras respostas são totalmente válidas aqui, mas, de alguma forma, leva algum tempo para digitar StringComparison.OrdinalIgnoreCasee também usar String.Compare.

Eu codifiquei o método de extensão String simples, onde você pode especificar se a comparação diferencia maiúsculas de minúsculas ou sem maiúsculas e minúsculas com booleano - veja a resposta a seguir:

https://stackoverflow.com/a/49208128/2338477

TarmoPikaro
fonte