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
제안하지 마십시오 ToLowerToLowerInvariant: 그들은 단지 비교를 수행하기 위해 메모리를 만들고, 새로운 문자 집합이 유니 코드에 추가로 그들이 실패 할 수 있습니다. 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 동안 찾고 사용 구문은 (오해의 소지가 조금있다 IgnoreCaseIgnoreCaseString(나는 그래서 자바 암시 권투 대 암시 언 박싱을 선택합니다)와 모호한는 생각 이의 문자열로 암시 적 캐스트 다시 자바에서이 것없는 일을). 그리고 이것은 각 비교에 대한 호출 트리 실행으로 표시된 사용 사례에 대한 여러 중첩 된 메소드 호출로 점프하는 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.