티스토리 뷰

C#

C# 문자열 비교 1

rewriter751 2016. 2. 2. 00:55

“초보자를 위한 C# and Database 완벽가이드”를 독학하면서 공부한 내용의 복습을 겸하여 블로깅하였다. 책의 설명만으로는 이해가 되지 않는 부분은 구글링을 통해 보충하였다. 참고한 문서는 아래 목록을 남겼다.

기본적인 문자열 비교

C#에서 문자열 비교는 string 클래스와 비교연사자(==, !=)를 이용한다.

namespace compare
{
    class Program
    {   
        static void Main(string[] args)
        {
            string str1 = "This a good map.";
            string str2 = "This ";
            str2 += "a good map.";      // str2 문자열에 "a good map." 추가
            string str3 = str2;

            Console.WriteLine("str1 문자열이 str2 문자열과 같은가요?: {0}", str1 == str2);  //True
            Console.WriteLine("str1 문자열이 str3 문자열과 같은가요?: {0}", str1 == str3);  //True
            Console.WriteLine("str2 문자열과 str3 문자열과 같은가요?: {0}", str2 == str3);  //True
            Console.ReadLine();

        }
    }
}

코드에서 보는 것과 같이 문자열 str1과 str2는 결국 같은 값인 “This a good map.”이라는 문장을 각각의 메모리상에 저장하게 된다. 그리고 str3는 str2의 값을 복사[1]하므로 str3 역시 str2와 같은 값을 메모리에 저장하게 된다. 즉 str1, str2, str3 각각의 메모리상에 같은 문장을 저장하게 되었다. 따라서 각 문자열의 비교에서 True를 출력한다.
사람의 관점에서 볼 때 위와 같은 처리가 자연스럽지만 C#의 입장에서 볼 때 이는 예외적인 처리에 따른 결과이다. C#에서 문자열 함수를 선언하기 위해 쓴 string은 단순한 자료형 키워드 같지만 실상은 class이다. 그것도 참조형 class인 것이다[2]. 그런데 string이 참조타입의 클래스이지만 비교는 값타입처럼 할 수 있다. 보통 객체와 같은 참조타입의 동일성 비교(==)는 참조 값을 비교하는 것인데 string은 참조가 아닌 값 자체(문자열)를 비교하도록 몇몇 연산자가 오버로딩되어 있기 때문에 위와 같은 결과가 나올 수 있는 것이다.
우선 문자열의 추가를 다시 생각해 보자. str2를 “This ”로 초기화하고 메모리상 그 다음 자리 “a good map.”를 이어 붙였다고 생각하는 것은 인간다운 추론이다. 그러나 C#에서는 처음 생성한 str2와 문자열이 추가된 str2는 서로 다른 객체이다. 즉 “This ”로 초기화된 str2와 별개로 “a good map.”라는 문자열이 추가된 새로운 객체(str2’, 이렇게 직접적으로 표현되지는 않지만)가 만들어지고 이것을 str2가 참조하는 방식으로 문자열 합이 이루어졌다. 이때 처음에 “This ”로 초기화한 str2는 가비지가 된다.

한데 위와 비슷하지만 각 문자열 변수를 object로 캐스팅하는 겅우에는 비교 결괏값이 조금 달라진다.

namespace compare
{
    class Program
    {   
        static void Main(string[] args)
        {
            string str1 = "This a good map.";
            string str2 = "This ";
            str2 += "a good map.";      // str2 문자열에 "a good map." 추가
            string str3 = str2;

            Console.WriteLine("str1 문자열이 str2 문자열과 같은가요?: {0}", (object)str1 == (object)str2);  //따라서 비교 결과는 false
            Console.WriteLine("str1 문자열이 str3 문자열과 같은가요?: {0}", (object)str1 == (object)str3);  //따라서 비교 결과는 false
            Console.WriteLine("str2 문자열과 str3 문자열과 같은가요?: {0}", (object)str2 == (object)str3);  //따라서 비교 결과는 ture
            Console.ReadLine();

        }
    }
}

위는 문자열 변수 앞에 “(object)”를 추가하여 각 문자열 변수의 성격을 바꾼 것이다. cast 연산자를 이용하여 값타입의 데이터형을 참조 타입의 데이터형으로 변환하였다. 따라서 메모리상에서 str1, str2는 별개의 메모리 공간(managed heap)에 “This is a good map.”이라는 값을 갖는다. 그리고 이러한 참조타입의 동일성 비교는 해당 값이 아닌 두 객체의 포인터, 즉 참조 값이 같은지를 확인하게 된다. 따라서 str1과 str2는 별개의 heap 참조 값을 비교하므로 False가 되며 str2의 참조 값을 대입한 str3와의 참조 값 비교에서는 True가 된다.

참고 문서

  1. C# 문자열 다루기
  2. C# 객체 동질성 관리하기

  1. 정말 복사 작업을 수행하는 것으로 이해를 했다. 그러나 참조형이므로 실제 값을 복사하는 방식이 아닌 참조 값을 복사한 것으로 보는 게 정확할 것이다.  ↩

  2. 문자열이라는 결국 char의 배열이라는 소리인데 c, C++에서 배열은 포인터, 즉 참조 방식을 통해 사용된다는 점을 상기해 보면 string이 참조형 class인 것은 당연한 귀결일지도 모르겠다.  ↩

Technorati Tags: ,

'C#' 카테고리의 다른 글

C# 문자열 비교 3::Compare()  (0) 2016.02.14
C# 문자열 비교 2::Equals()  (0) 2016.02.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함