C # 대소 문자를 구분하지 않는 equals 연산자가 있습니까?


156

다음은 대소 문자를 구분한다는 것을 알고 있습니다.

if (StringA == StringB) {

그래서 두 문자열을 둔감하게 비교하는 연산자가 있습니까?



누군가가 Dictionary <string, int>에 대해 대소 문자를 구분하지 않는 비교를 찾고이 질문을 우연히 발견하는 경우 여기 에서이 질문을 살펴보십시오. 일반 사전에 대한 대소 문자를 구분하지 않는 액세스
— Robotnik

정말 좋을 것입니다; 대응 정의 말하는 ~=평행 ==대소 문자를 구분 버전으로.
— eidylon

만약 마이크로 소프트 개발자들이 이것을 본다면, 다음 버전의 csharp에서는 대소 문자를 구분하지 않는 연산자가 필요하다고 생각합니다. 이 string.Equal ()은 길다.
— Rez.Net

답변:


288

이 시도:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

나는 상대적인 StackOverflow 초보자입니다. 링크를 추가하여 의미를 설명 할 수 있습니까? MSDN 문서를 의미합니까?
— John Feminella 2016 년

55
문화권 비교를 원하면이 방법을 사용하십시오. "FILE"과 "file"이 모두 허용되도록하려면 "OrdinalIgnoreCase"를 사용하십시오. 그렇지 않으면 터키어 로켈과 같은 장소에서 코드가 작동하지 않을 수 있습니다. 자세한 내용은 moserware.com/2008/02/does-your-code-pass-turkey-test.html
— Jeff Moser

10
사무엘이 무슨 말을하는지 모르겠다 ... 정확하고 자명하다. 참조가 필요하지 않습니다. +1
— 세일링 유도

3
아아, 이건 정말 끔찍한 입이다! 키보드가 마모됩니다. " if A$=B$ then goto 10"를 사용할 수있는 시대는 지났습니다
— Sanjay Manohar

9
@ Sanjay Manohar 그런 다음 사용자 정의 연산자를 작성하십시오-더 나은 키보드를 권장합니다.
— Rushyo

37

대소 문자를 무시하고 두 문자열을 비교 하는 가장 좋은 방법 은 String.Equals 정적 메서드를 사용하여 서수 무시 문자열 비교를 지정하는 것입니다. 또한 문자열을 소문자 나 대문자로 변환 한 후 비교하는 것보다 훨씬 빠른 방법입니다.

두 가지 접근 방식의 성능을 테스트했으며 서수 무시 문자열 비교가 9 배 이상 빨랐습니다 ! 문자열을 소문자 또는 대문자로 변환하는 것보다 안정적입니다 (터키어 i 문제를 확인하십시오). 따라서 항상 String.Equals 메소드를 사용하여 문자열이 동일한 지 비교하십시오.

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

문화권 별 문자열 비교를 수행하려는 경우 다음 코드를 사용할 수 있습니다.

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

두 번째 예는 현재 문화권의 문자열 비교 논리를 사용하므로 첫 번째 예의 "단일 무시 무시"비교보다 느리므로 문화권 별 문자열 비교 논리가 필요하지 않은 경우 최대 성능을 유지 한 후에는 "단일 무시 무시"비교를 사용하십시오.

자세한 내용 은 내 블로그에서 전체 기사를 읽으십시오 .


1
제안하지 마십시오 ToLower나 ToLowerInvariant: 그들은 단지 비교를 수행하기 위해 메모리를 만들고, 새로운 문자 집합이 유니 코드에 추가로 그들이 실패 할 수 있습니다. ToUpper특히 터키의 'i'때문에 실패합니다. ToLower비슷한 이유로 미래에 실패하지 않는 이유 는 없습니다.
— antiduh

@antiduh, 귀하의 의견에 감사드립니다. 대부분의 사람들은 이러한 잠재적 인 문제를 알고 있으며 인터넷을 통한 많은 자습서는 터키어 'i'를 예로 들어 설명합니다. 내 게시물에서 볼 수 있듯이 ToLower또는 ToLowerInvariant방법을 사용하지 않는 것이 좋습니다 String.Equals. 방법이 얼마나 효율적인지 보여주고 싶었습니다 .
— Pavel Vladov

3
"대부분의 사람들은 이러한 잠재적 인 문제에 대해 알고 있습니다. 인터넷을 통한 많은 튜토리얼은 터키어 'i'를 예로 들어줍니다."사람들이 많지 않아서 여전히 답의 두 번째 문장으로 언급하고 있습니다. 또한, 당신의 대답 에는 그것을 사용하지 않을 충분한 정당성이 포함되어 있지 않습니다-당신은 단순히 성과를 언급합니다. 성능이 항상 최우선 순위는 아닙니다. 결과적으로 현재 도움말 센터 가이드 라인을 위반하고 있습니다. 외부 사이트에 대한 링크는 괜찮지 만 내용을 충분히 요약하지 못했습니다 (터키 'i'문제). 광고 플랫폼이 아닙니다.
— antiduh

20

StringComparer정적 클래스에는 원하는 모든 유형의 대소 문자 구분에 대한 비교자를 반환 하는 여러 속성 이 있습니다.

StringComparer 속성

예를 들어

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

또는

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

인수 를 취하는 과부하 string.Equals또는 string.Compare과부하 보다 약간 깨끗합니다 StringComparison.


15
System.Collections.CaseInsensitiveComparer

또는

System.StringComparer.OrdinalIgnoreCase

이것이 전체 응용 프로그램에 영향을 줍니까?
— GateKiller 2016 년

3
이에 대한 자세한 정보는 어디서 찾을 수 있습니까? 이것은 대소 문자를 구분하지 않는 일치에 ==를 사용할 수 있음을 의미합니까?
— GateKiller 2016 년

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

8

또는

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

그러나 StringA가 null이 아닌지 확인해야합니다. 따라서 아마도 더 나은 사용법입니다.

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

요한이 제안한대로

편집 : 버그 수정


4

당신이 사용할 수있는

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))

3

운영자? 아니요, 그러나 문자열 비교가 대소 문자를 구분하지 않도록 문화를 변경할 수 있다고 생각합니다.

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

equals 연산자로 문자열을 비교하는 방식이 변경 될 것이라고 확신합니다.


예, 적어도 모든 문자열 비교가 대소 문자를 구분하지 않는 한 원하는 것은 아닙니다. 그러나 그것이 equals 연산자의 동작을 변경한다고 생각합니다.
— John Leidegren

3

구문을 단순화하는 아이디어는 다음과 같습니다.

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);
    }
}

다음과 같이 사용 가능

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true

깨끗한 같은 I 동안 찾고 사용 구문은 (오해의 소지가 조금있다 IgnoreCase대 IgnoreCaseString(나는 그래서 자바 암시 권투 대 암시 언 박싱을 선택합니다)와 모호한는 생각 이의 문자열로 암시 적 캐스트 다시 자바에서이 것없는 일을). 그리고 이것은 각 비교에 대한 호출 트리 실행으로 표시된 사용 사례에 대한 여러 중첩 된 메소드 호출로 점프하는 2 개의 새 오브젝트의 메모리 오버 헤드를 작성합니다. 즉, 대부분의 경우 성능이 충분할 것입니다.
— Arkaine55

이것은 영리한 아이디어이지만 유지 관리 측면에서 현명한 것은 아닙니다. 시스템의 내장 문자열 유형을 사용하는 대신 대리 문자열 유형을 효과적으로 작성하고 있습니다. 프로그래머는 그 다음에 무슨 일이 일어나고 있는지 이해하지 못하고 당신에게 욕을 할 것입니다. string.Equals ()를 사용하는 것이 실제로 그렇게 나쁜 것은 아니며 대부분의 사람들은 그것이하는 일을 이해할 것입니다.
— ntcolonel

1

이 비교 방법의 끝에 입력하는 데 익숙합니다. , StringComparison.

그래서 확장했습니다.

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

thisStringext를 호출하기 전에 null을 확인해야합니다 .


1
현재 .NET Framework 버전에서이 기본 제공 방법과 동일합니까? docs.microsoft.com/en-gb/dotnet/api/…
— Bernard Vander

1
그렇게 나타납니다. .net의 이후 버전에 지금이 포함 된 것 같습니다.
— Valamas

.NET 4.5 및 모든 .NET Core 버전부터 사용 가능합니다.
— Bernard Vander는


0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

사람들은 ToUpperInvariant ()가 ToLowerInvariant ()보다 빠르다고보고합니다.


1
현재 또는 원하는 문화권에 대소 문자에 대한 특별한 규칙이있는 경우 불변은 잘못된 생각 일 수 있습니다.
— OregonGhost 2016 년

각 문자열의 새 사본을 작성합니까? 그렇다면 나쁜 생각입니다.
— cjk 2016 년

1
또한 문자열 중 하나 (또는 ​​둘 다)가 null 인 경우 예외가 발생합니다.
— tvanfosson 2016 년

3
성능 측면에서, 여기에 2 개의 새 문자열 인스턴스를 작성하는 것처럼 좋은 해결책은 아닙니다.
— Frederik Gheysels

0

다른 답변은 여기에서 완전히 유효하지만 어떻게 든 입력 StringComparison.OrdinalIgnoreCase하고 사용 하는 데 시간이 걸립니다 String.Compare.

비교가 대소 문자를 구분하는지 또는 부울을 사용하여 대소 문자를 구분하지 않는지 지정할 수있는 간단한 문자열 확장 방법을 코딩했습니다. 다음 답변을 참조하십시오.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.