문제

C#에서 문자열을 비교하는 것은 매우 간단합니다.실제로 이를 수행하는 방법에는 여러 가지가 있습니다.아래 블록에 일부를 나열했습니다.내가 궁금한 점은 이들 사이의 차이점과 언제 다른 것보다 사용해야 하는가입니다.어떤 희생을 치르더라도 피해야 합니까?내가 나열하지 않은 것이 더 있나요?

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

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

(메모:나는 이 예에서 평등을 찾고 있습니다. 그 이상도 이하도 아니지만 이에 대해서도 자유롭게 의견을 제시해 주세요.)

도움이 되었습니까?

해결책

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

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()null 문자열은 가져옵니다 null 참조 예외, 켜져 있는 동안 == 하지 않습니다.

Object.ReferenceEquals(stringValue, otherStringValue)

참조가 동일한지 확인하세요.이는 동일한 내용을 가진 두 개의 문자열이 아니라 문자열 개체 자체를 비교하는 것입니다.


메서드 호출을 사용하는 위의 옵션에는 비교 방법을 지정하는 추가 옵션이 포함된 오버로드가 있습니다.

단지 평등성을 확인하고 싶다면 문화에 따른 비교를 사용할지 여부를 결정한 다음 다음을 사용하라는 조언이 있습니다. .CompareTo 또는 .Equals, 선택에 따라.

다른 팁

MSDN에서:

"비교 방법은 주로 분류 또는 알파벳 화 작업에 사용하도록 설계되었습니다.메소드 호출의 기본 목적은 두 문자열이 동등한 지 여부를 결정하는 경우 사용해서는 안됩니다.두 줄이 동등한 지 여부를 확인하려면 Equals 메소드를 호출하십시오. "

그들은 다음을 사용할 것을 제안합니다. .Equals 대신에 .CompareTo 평등만을 추구할 때.사이에 차이가 있는지 잘 모르겠습니다. .Equals 그리고 == 위해 string 수업.가끔 이용하겠습니다 .Equals 또는 Object.ReferenceEquals 대신에 == 누군가 나중에 와서 수업을 재정의할 경우를 대비해 내 수업을 위해 == 해당 클래스의 연산자입니다.

BCL 방식의 차이점이 궁금하시다면, 반사기 당신의 친구입니다 :-)

나는 다음 지침을 따릅니다.

정확히 일치: 편집하다:나는 이전에 Equals(string, string) 내에서 객체 == 연산자가 객체 참조를 비교하는 데 사용된다는 원칙에 따라 항상 == 연산자를 사용했지만 strA.Equals(strB)는 여전히 문자열보다 전반적으로 1-11% 더 빠른 것 같습니다. 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

처럼 에드 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;

문자열 비교 문제에 대한 좋은 설명과 사례는 기사에서 찾을 수 있습니다. Microsoft .NET 2.0에서 문자열 사용에 대한 새로운 권장 사항 그리고 또한 .NET Framework에서 문자열을 사용하는 모범 사례.


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

  • 현재문화
  • 현재문화IgnoreCase
  • 불변문화
  • 불변문화IgnoreCase
  • 서수
  • 서수대소문자 무시

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

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

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


String.CompareTo 메서드(문자열)

실제로 유형 안전 구현은 다음과 같습니다. IComparable.CompareTo 메서드.기본 해석:현재문화.

용법:

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

따라서

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

String.Compare 메서드

정적 멤버 문자열 클래스 과부하가 많습니다.기본 해석:현재문화.

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

String.Equals 메서드

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

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


StringComparer 클래스

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

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

일반적으로 이 작업을 수행해야 하는 99%의 경우 성능이 중요하지는 않지만 루프에서 이 작업을 수백만 번 수행해야 하는 경우 .Equals 또는 ==를 사용하는 것이 좋습니다. 문자를 찾자마자 바로 사용하기 때문입니다. 일치하지 않으면 모든 것이 거짓으로 처리되지만 CompareTo를 사용하면 어느 문자가 다른 문자보다 작은지 파악해야 하므로 성능 시간이 약간 더 나빠집니다.

앱이 다른 국가에서 실행될 경우 CultureInfo의 의미를 살펴보고 가능하면 .Equals를 사용하는 것이 좋습니다.나는 실제로 미국용 앱만 작성하기 때문에(누군가가 제대로 작동하지 않더라도 상관하지 않음) 항상 ==만 사용합니다.

여기에 나열된 양식에서는 둘 사이에 큰 차이가 없습니다. CompareTo 결국 전화를 걸고 CompareInfo 현재 문화권을 사용하여 비교하는 방법입니다. Equals 에 의해 호출됩니다 == 운영자.

과부하를 고려하면 상황이 달라집니다. Compare 그리고 == 현재 문화권만 사용하여 문자열을 비교할 수 있습니다. Equals 그리고 String.Compare 걸릴 수 있습니다 StringComparison 문화권을 구분하지 않거나 대소문자를 구분하지 않는 비교를 지정할 수 있는 열거형 인수입니다.오직 String.Compare 다음을 지정할 수 있습니다. CultureInfo 기본 문화권이 아닌 다른 문화권을 사용하여 비교를 수행합니다.

다용도로 사용하기 때문에 String.Compare 그 어떤 비교 방법보다내가 원하는 것을 정확하게 지정할 수 있습니다.

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

       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");
  • s1.비교대상(s2): 주요 목적이 두 문자열이 동일한지 확인하는 것이라면 사용하지 마세요.
  • s1 == s2: 사례를 무시할 수 없습니다.
  • s1.Equals(s2, 문자열비교): s1이 null인 경우 NullReferenceException이 발생합니다.
  • 문자열.Equals(s2, 문자열비교): 제거 과정을 통해 이 공전 방법은 우승자 (두 문자열이 동일한지 확인하는 일반적인 사용 사례를 가정)!

.Equals를 사용하는 것도 훨씬 쉽습니다. 읽다.

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

그런데, 이건 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을 반환하고 a.Equals(b)가 true인 경우 0을 반환하는 문자열의 CompareTo 함수를 호출합니다. >0 그렇지 않으면.그러나 이는 대소문자를 구분하므로 CompareTo에서 대소문자 등을 무시하는 옵션이 있을 수 있지만 지금은 살펴볼 시간이 없습니다.다른 사람들이 이미 언급했듯이 이것은 정렬을 위해 수행됩니다.이러한 방식으로 동등성을 비교하면 불필요한 오버헤드가 발생합니다.

나는 내용을 생략할 것이라고 확신하지만, 더 자세한 내용이 필요한 경우 실험을 시작하기에 충분한 정보라고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top