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


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

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

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

(참고 : 나는이 예에서 평등을 찾고 있는데, 작거나 같지 않지만 그것에 대해서도 자유롭게 의견을 말함)




Answers


다음은 이러한 함수가 작동하는 방법에 대한 규칙입니다.

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. null 문자열에서 .Equals ()를 호출하면 null 참조 예외가 발생하지만, ==는 null 참조 예외를 가져옵니다.

Object.ReferenceEquals (stringValue, otherStringValue) :

참조가 동일하다는 것을 확인하십시오. 같은 내용을 가진 두 개의 문자열이 아니라 문자열 개체를 자체와 비교하는 것입니다.

메서드 호출을 사용하는 위의 옵션을 사용하면 비교 방법을 지정하는 옵션이 더 많은 오버로드가 있음에 유의하십시오.

당신이 단지 평등을 확인하기를 원한다면 나의 충고는 문화에 의존하는 비교를 사용하기를 원하는 마음을 채운 다음, 선택에 따라 .CompareTo 또는 .Equals를 사용하는 것입니다.




MSDN에서 :

"CompareTo 메서드는 주로 정렬 작업이나 알파벳순으로 사용하기 위해 디자인되었으므로 메서드 호출의 주 목적은 두 문자열이 같은지 여부를 확인하는 것이므로 사용해서는 안됩니다. 두 문자열이 동일한 지 여부를 확인하려면 Equals 메서드를 호출하십시오. "

이들은 평등만을 바라 볼 때 .Equals 대신 .Equals 를 사용할 것을 제안합니다. string 클래스에 대해 .Equals== 사이에 차이가 있는지 확실하지 않습니다. 나중에 누군가가오고 그 클래스에 대해 == 연산자를 재정의하는 경우에 대비 Object.ReferenceEquals 때로는 .Equals 또는 Object.ReferenceEquals 를 사용 Object.ReferenceEquals 내 자신의 클래스에 == 를 추가합니다.




BCL 방식의 차이점에 대해 궁금한 점이 있으시면 Reflector 가 귀하의 친구입니다 :-)

나는 다음 지침을 따른다.

정확히 일치 : 편집 : 나는 == 연산자를 항상 == 연산자를 사용하여 Equals (string, string) 안의 object == 연산자가 객체 참조를 비교하는 데 사용되지만 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

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

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

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

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



Ed가 말했듯이, 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);

간단한 이유는 다음과 같은 예외가 throw됩니다 :

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

bool equal = a.Equals(b);

그리고 다음은하지 않습니다 :

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

bool equal = a == b;



문자열 비교 문제에 대한 설명과 사례 는 Microsoft .NET 2.0의 문자열 사용에 대한 새로운 권장 사항.NET Framework의 문자열 사용에 대한 유용한 정보에서 확인할 수 있습니다.

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

  • 현재 문화
  • CurrentCultureIgnoreCase
  • 불변 문화
  • InvariantCultureIgnoreCase
  • 서수
  • 서수

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

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

문자열 비교 메서드에 대한 오버로드뿐만 아니라 StringComparison 열거 형 은 .NET 2.0 이후에 존재합니다.

String.CompareTo 메서드 (String)

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

용법:

CompareTo 메서드는 주로 정렬 작업이나 알파벳순으로 사용하기 위해 디자인되었습니다.

그러므로

IComparable 인터페이스를 구현하려면이 메서드를 사용해야합니다.

String.Compare 메서드

오버로드가 많은 String 클래스 의 정적 멤버입니다. 기본 해석 : CurrentCulture.

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

String.Equals 메서드

Object 클래스에서 재정의하고 유형 안전을 위해 오버로드되었습니다. 기본 해석 : 서수. 그것을주의해라:

String 클래스의 동등성 메서드에는 정적 같음 , 정적 연산자 ==인스턴스 메서드 같음이 포함 됩니다.

StringComparer 클래스

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

StringComparer 클래스 를 사용하여 유형별 비교를 생성하여 일반 컬렉션의 요소를 정렬 할 수 있습니다. Hashtable, Dictionary, SortedList 및 SortedList와 같은 클래스는 정렬 목적으로 StringComparer 클래스를 사용합니다.




그 성능은 일반적으로 99 %의 시간에 문제가되지 않지만, 이것을 반복해야한다면 몇 백만 번 반복하면됩니다 .Equals 또는 ==를 사용하는 것이 좋습니다. 문자를 찾자 마자 그것과 일치하지 않는 것은 모든 것을 false로 던집니다. 그러나 CompareTo를 사용하면 어떤 캐릭터가 다른 캐릭터보다 작아서 성능이 약간 떨어질 수 밖에 없습니다.

앱이 다른 국가에서 운영되는 경우 CultureInfo에 대한 의미를 살펴보고 .Equals를 사용하는 것이 좋습니다. 나는 정말 미국을위한 앱을 작성하기 때문에 (누군가가 제대로 작동하지 않는지 상관하지 않는다.) 항상 ==를 사용한다.




여기에 나열된 양식에는이 두 가지 사이에 큰 차이가 없습니다. CompareTo 는 현재 culture를 사용하여 비교를 수행하는 CompareInfo 메서드를 호출합니다. Equals== 연산자에 의해 호출됩니다.

과부하를 고려하면 상황이 달라집니다. Compare== 는 현재 culture를 사용하여 문자열을 비교할 수만 있습니다. EqualsString.Compare 는 문화권 구분 또는 대 / 소문자 비 구분 비교를 지정할 수 있도록 StringComparison 열거 인수를 사용할 수 있습니다. String.Compare 만이 CultureInfo 를 지정하고 기본 culture가 아닌 다른 culture를 사용하여 비교를 수행 할 수 있습니다.

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




주의해야 할 큰 차이점은 .Equals ()는 첫 번째 문자열이 null 인 경우 예외를 throw하지만 Where ==는 예외가 아닙니다.

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



.Equals를 사용하면 읽기가 훨씬 쉽습니다.




CompareTo 는 문자열을 문자열 객체와 비교하고 int 값을 반환합니다. 값이 0이면 문자열이 동일 함을 의미합니다.

string country = "southindia";
object ob1 = country.Clone();
Console.WriteLine( country.CompareTo(ob1));

string country = "southindia";
string cou = "insia";
int n = country.CompareTo(cou);
Console.WriteLine( n );



.Equals를 사용하면 StringComparison 옵션도 얻을 수 있습니다. 케이스 및 다른 것들을 무시하기에 매우 편리합니다.

btw, false로 평가됩니다.

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

return a==b

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

b를로 변경하면 :

b = "MYSTRING";

a.Equals (b)는 거짓이지만

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

사실 일 것이다.

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

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