C #에서 문자열 비교 방법의 차이점


261

C #에서 문자열을 비교하는 것은 매우 간단합니다. 실제로 몇 가지 방법이 있습니다. 아래 블록에 일부를 나열했습니다. 내가 궁금한 점은 그들 사이의 차이점과 다른 것들을 사용해야 할 때의 차이점입니까? 모든 비용을 피해야합니까? 내가 나열하지 않은 것이 더 있습니까?

string testString = "Test";
string anotherString = "Another";

if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}

(참고 :이 예에서 평등을 찾고 있습니다. 이보다 작거나 크지 않지만 자유롭게 의견을 말하십시오)


4
한 가지 트랩은 stringValue.Equals (null)을 수행 할 수 없다는 것입니다. 이는 null에서 메소드를 호출 할 수 있다고 가정하므로
johnc


@RobertHarvey 내가 stackoverflow에 온 이유는 대답을 위해 여러 페이지를 읽을 필요가 없기 때문입니다.
Syaiful Nizam Yahya

@Syaiful : 내가 스택 오버플로에 온 이유 는 문서에 없는 답변을 찾는 것입니다 .
Robert Harvey

답변:


231

이러한 기능의 작동 방식에 대한 규칙은 다음과 같습니다.

stringValue.CompareTo(otherStringValue)

  1. null 문자열 앞에 온다
  2. 그 사용 CultureInfo.CurrentCulture.CompareInfo.Compare은 배양 종속 비교를 사용하는 방법. 이것은 독일 ß과 동등 SS하거나 비슷 하다는 것을 의미 할 수 있습니다.

stringValue.Equals(otherStringValue)

  1. null 아무것도 같지 않다
  2. StringComparison옵션 을 지정하지 않으면 직접 서수 평등 검사처럼 보이는 것, 즉 언어 나 문화 ß와 동일하지 않은 것을 사용합니다.SS

stringValue == otherStringValue

  1. 와 동일하지 않습니다 stringValue.Equals().
  2. ==연산자 정적 호출 Equals(string a, string b)다시 내부로 이동 방법 ( EqualsHelper비교를 수행한다.
  3. 호출 .Equals()A의 null문자열은 도착 null에가있는 동안, 참조 예외를 ==하지 않습니다.

Object.ReferenceEquals(stringValue, otherStringValue)

참조가 동일한 지 확인합니다. 즉, 내용이 같은 두 개의 문자열이 아니라 문자열 객체와 자체를 비교하는 것입니다.


메소드 호출을 사용하는 위의 옵션에는 비교 방법을 지정하는 옵션이 많은 과부하가 있습니다.

그냥 어떤지를 확인하려면 내 조언은 사용 다음 문화에 의존 비교 사용 여부를 당신의 마음을 확인하는 것입니다 .CompareTo또는 .Equals선택에 따라.


5
"stringValue.Equals (otherStringValue) : null이 null과 같지 않습니다"Lol, 그렇지 않습니다. null은 ObjectReferenceNotSet 예외와 같습니다.
케빈

29
==는 .Equals ()와 같지 않습니다. == 연산자는 정적 Equals (string a, string b) 메소드를 호출합니다 (이는 내부 EqualsHelper로 이동하여 비교를 수행합니다. .Equals on a null on ==하지 않는 동안 문자열은 null 참조를 얻습니다
Dan C.

2
반면에 .Equals는 약간 빠르지 만 (내부 하나의 메서드 호출은 적음) 물론 읽기 쉽지는 않습니다.
Dan C.

'=='는 참조 비교를 수행하고 object.equals는 값 비교를 수행한다고 생각했습니다. '=='와 string.equals는 어떻게 동일하게 작동합니까?
amesh

@ LasseV.Karlsen 귀하의 의견은 String.Compare무엇입니까?
JDandChips

72

MSDN에서 :

"CompareTo 메서드는 주로 정렬 또는 알파벳순으로 정렬 작업에 사용하도록 설계되었습니다. 메서드 호출의 주요 목적은 두 문자열이 같은지 여부를 확인하는 데 사용해서는 안됩니다. 두 문자열이 같은지 여부를 확인하려면 Equals 메서드를 호출하십시오. "

그들은 평등만을 찾을 때 .Equals대신에 사용 하는 것이 좋습니다 .CompareTo. 나는 차이가 있는지 확실하지 오전 .Equals==에 대한 string클래스. 누군가가 나중에 와서 해당 클래스 의 연산자를 재정의하는 경우를 대비 하여 때때로 내 수업 대신 .Equals또는 Object.ReferenceEquals대신에 사용 합니다.====


18
그게 당신에게 일어난 적이 있습니까? (Redefining ==) ... 나는 그것을 너무 방어적인 프로그래밍으로 본다 =)
juan

그렇기 때문에 객체 평등을 찾을 때 Object.ReferenceEquals를 사용하는 이유는 다음과 같습니다. :). 과도하게 방어적일 수 있지만, 나는 그것에 대해 열광적이지 않으며 진실로이 상황은 자주 나타나지 않습니다.
Ed S.

이 '방어 적 코딩'이 유용한 지 의심 스럽다. 클래스 소유자가 == 연산자를 재정의해야하는 경우 아무도 사용하지 않는 것을 어떻게 알 수 있습니까?
Dave Van den Eynde

1
@DaveVandenEynde : 예 ... 나는 이것을 잠시 동안 썼습니다. 나는 이것을 정기적으로하지 않고.
Ed S.

1
Microsoft의 권장 사항은 다음과 같습니다. .NET Framework에서 문자열을 사용하는 모범 사례
JJS

50

BCL 방법의 차이점에 대해 궁금한 점이 있다면 Reflector 가 당신의 친구입니다 :-)

다음 지침을 따릅니다.

정확히 일치 : 편집 : 이전에는 항상 Equals (string, string) 내부에서 객체 == 연산자를 사용하여 객체 참조를 비교하지만 strA.Equals (strB)는 여전히 1-11 % 인 원칙에 따라 == 연산자를 사용했습니다. string.Equals (strA, strB), strA == strB 및 string.CompareOrdinal (strA, strB)보다 전체적으로 빠릅니다. 내부 / 비 간격 문자열 값, 동일 / 다른 문자열 길이 및 다양한 크기 (1B-5MB) 모두에서 StopWatch로 루프 테스트를 수행했습니다.

strA.Equals(strB)

사람이 읽을 수있는 일치 (서양 문화, 대소 문자 구분) :

string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0

사람이 읽을 수있는 일치 (CityInfo에 의해 정의 된 다른 모든 문화권, 대소 문자 구분 / 악센트 / 가나 등) :

string.Compare(strA, strB, myCultureInfo) == 0

사용자 지정 규칙과 사람이 읽을 수있는 일치 (다른 모든 문화권) :

CompareOptions compareOptions = CompareOptions.IgnoreCase
                              | CompareOptions.IgnoreWidth
                              | CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

18

에드는 말했다 compareTo와 정렬에 사용됩니다.

그러나 .Equals와 ==에는 차이가 있습니다.

== 본질적 으로 다음 코드로 해결됩니다 .

if(object.ReferenceEquals(left, null) && 
   object.ReferenceEquals(right, null))
    return true;
if(object.ReferenceEquals(left, null))
    return right.Equals(left);
return left.Equals(right);

간단한 이유는 다음과 같은 경우 예외가 발생하기 때문입니다.

string a = null;
string b = "foo";

bool equal = a.Equals(b);

그리고 다음은 그렇지 않습니다.

string a = null;
string b = "foo";

bool equal = a == b;

15

문자열 비교 문제에 대한 자세한 설명과 실습은 Microsoft .NET 2.0의 문자열 사용에 대한 새로운 권장 사항 기사 와 .NET Framework의 문자열 사용에 대한 모범 사례 문서에서 찾을 수 있습니다 .


언급 된 각 방법 (및 기타)에는 특별한 목적이 있습니다. 그들 사이의 주요 차이점은 기본적으로 사용하는 StringComparison 열거의 종류입니다 . 몇 가지 옵션이 있습니다.

  • 현재 문화
  • CurrentCultureIgnoreCase
  • 불변의 문화
  • 불변 문화 무시
  • 서수
  • 서수 무시

위의 각 비교 유형은 서로 다른 사용 사례를 대상으로합니다.

  • 서수
    • 대소 문자 구분 내부 식별자
    • XML 및 HTTP와 같은 표준의 대소 문자 구분 식별자
    • 대소 문자 구분 보안 관련 설정
  • 서수 무시
    • 대소 문자를 구분하지 않는 내부 식별자
    • XML 및 HTTP와 같은 표준에서 대소 문자를 구분하지 않는 식별자
    • 파일 경로 (Microsoft Windows)
    • 레지스트리 키 / 값
    • 환경 변수
    • 리소스 식별자 (예 : 핸들 이름)
    • 대소 문자를 구분하지 않는 보안 관련 설정
  • InvariantCulture 또는 InvariantCultureIgnoreCase
    • 언어 적으로 관련된 일부 데이터
    • 고정 정렬 순서가 필요한 언어 데이터 표시
  • CurrentCulture 또는 CurrentCultureIgnoreCase
    • 사용자에게 표시되는 데이터
    • 대부분의 사용자 입력

참고 것을 StringComparison 열거 뿐만 아니라 문자열 비교 방법에 대한 오버로드, .NET 2.0부터 존재한다.


String.CompareTo 메서드 (문자열)

실제로 IComparable.CompareTo 메서드 의 형식 안전 구현입니다 . 기본 해석 : CurrentCulture.

용법:

CompareTo 메서드는 주로 정렬 또는 알파벳순으로 작업하는 데 사용하도록 설계되었습니다

그러므로

IComparable 인터페이스를 구현하면 반드시이 방법을 사용해야합니다

String.Compare 메소드

과부하가 많은 String 클래스 의 정적 멤버입니다 . 기본 해석 : CurrentCulture.

가능하면 StringComparison 매개 변수가 포함 된 Compare 메서드의 오버로드를 호출해야합니다.

String.Equals 메서드

객체 클래스에서 오버라이드되고 타입 안전을 위해 오버로드됩니다. 기본 해석 : 서수. 그것을주의해라:

String 클래스의 동등성 메소드에는 정적 Equals , 정적 연산자 ==인스턴스 메소드 Equals가 포함 됩니다.


StringComparer 클래스

문자열 비교를 처리하는 다른 방법은 특히 정렬을 목표로합니다.

당신은 사용할 수 있습니다 StringComparer 클래스를 일반적인 컬렉션의 요소를 정렬하는 형식 고유의 비교를 만들 수 있습니다. Hashtable, Dictionary, SortedList 및 SortedList와 같은 클래스는 정렬을 위해 StringComparer 클래스를 사용합니다.


2
SO에 대한 다른 게시물에 따르면 서수 이외의 모든 방법에는 Compare (a, b) 및 Compare (b, a)가 모두 1을 반환 할 수 있으며 버그는 "수정되지 않음"으로 분류됩니다 ". 따라서, 나는 그러한 비교가가 확실하지 않다 어떤 사용 사례.
supercat

@supercat 당신은 그것에 연결하거나 예를 들어 줄 수 있습니까?
녹 티스

1
문제에 대한 설명은 stackoverflow.com/questions/17599084/… 를 참조하십시오 .
supercat 2011

7

그 성능은 일반적으로 99 %의 시간으로 중요하지 않지만, 수백만 번 반복 하여이 작업을 수행 해야하는 경우 문자를 발견하자마자 .Equals 또는 ==을 사용하는 것이 좋습니다. 일치하지 않으면 전체 내용이 거짓으로 표시되지만 CompareTo를 사용하면 다른 문자보다 적은 문자를 찾아서 성능 시간이 약간 떨어집니다.

앱이 다른 국가에서 실행될 경우 CultureInfo의 의미를 살펴보고 .Equals를 사용하는 것이 좋습니다. 나는 실제로 미국을위한 앱을 작성하기 때문에 (그리고 누군가가 제대로 작동하지 않는다면 신경 쓰지 않기 때문에) 항상 ==를 사용합니다.


5

여기에 나와있는 양식에는 둘 사이에 큰 차이가 없습니다. 현재 문화권을 사용하여 비교를 수행 CompareTo하는 CompareInfo메소드를 호출합니다 . 연산자 Equals가 호출합니다 ==.

과부하를 고려하면 상황이 달라집니다. Compare그리고 ==단지 문자열을 비교하는 현재의 문화를 사용할 수 있습니다. EqualsString.Compare테이크 수 있습니다 StringComparison당신이 문화를 구분 또는 대소 문자를 구분 비교를 지정할 수 있습니다 열거 인수를. 기본 문화권 이외의 문화권을 사용하여 a 만 String.Compare지정하고 CultureInfo비교를 수행 할 수 있습니다 .

그 다양성으로 인해 String.Compare다른 비교 방법보다 더 많이 사용합니다 . 내가 원하는 것을 정확하게 지정할 수 있습니다.


2

주목해야 할 한 가지 큰 차이점은 첫 번째 문자열이 null 인 경우 .Equals ()는 예외를 throw하는 반면 ==는 그렇지 않습니다.

       string s = null;
        string a = "a";
        //Throws {"Object reference not set to an instance of an object."}
        if (s.Equals(a))
            Console.WriteLine("s is equal to a");
        //no Exception
        if(s==a)
            Console.WriteLine("s is equal to a");

0
  • s1.CompareTo (s2) : 두 문자열이 동일한 지 여부를 결정하는 것이 주 목적인 경우 사용하지 마십시오
  • s1 == s2 : 대소 문자를 무시할 수 없습니다
  • s1.Equals (s2, StringComparison) : s1이 null 인 경우 NullReferenceException이 발생 함
  • String.Equals (s2, StringComparison) :정적 메소드는 제거 과정 에서 WINNER입니다 (두 문자열이 동일한 지 여부를 판별하기위한 일반적인 사용 사례를 가정)!


-9

.Equals를 사용하면 StringComparison 옵션도 얻을 수 있습니다. 케이스 및 기타 사항을 무시하는 데 매우 편리합니다.

btw, 이것은 거짓으로 평가됩니다

string a = "myString";
string b = "myString";

return a==b

==는 포인터 인 a와 b의 값을 비교하기 때문에 포인터가 메모리에서 동일한 객체를 가리키는 경우에만 true로 평가됩니다. 같음은 포인터를 역 참조하고 포인터에 저장된 값을 비교합니다. a. 여기에서 같음 (b)이 참입니다.

b를 다음과 같이 변경하면

b = "MYSTRING";

a. 같음 (b)은 거짓이지만

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

사실 일 것이다

a.CompareTo (b)는 포인터의 값을 비교하는 문자열의 CompareTo 함수를 호출하고 a에 저장된 값이 b에 저장된 값보다 작은 경우 <0을 반환하고 a.Equals (b)가 true 인 경우 0을 반환합니다. 그렇지 않으면> 0입니다. 그러나 이것은 대소 문자를 구분합니다. CompareTo에는 대소 문자를 무시할 수있는 옵션이 있다고 생각하지만 지금 볼 시간이 없습니다. 다른 사람들이 이미 언급했듯이 이것은 정렬을 위해 수행됩니다. 이러한 방식으로 평등을 비교하면 불필요한 오버 헤드가 발생합니다.

나는 물건을 남기지 않을 것이라고 확신하지만, 더 자세한 정보가 필요하면 실험을 시작하기에 충분한 정보라고 생각합니다.


9
a == b 부분이 잘못되었습니다. == 연산자는 String 클래스에 대해 효과적으로 오버로드되며 실제 참조에 관계없이 값을 비교합니다.
Goyuix
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.