NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# 4. String 형식

    페이지 정보

    본문

    안녕하세요. 소심비형입니다. 프로그래밍 언어에서 가장 많이 사용되는 대표적인 자료형인 String에대해 알아보겠습니다. 이 내용을 읽기 전에 한가지 명확하게 인지해야 하는 내용이 있습니다. C# 또는 Java에서 제공하는 기본 자료형중에 유일하게 String만 Primitive Type이 아닌 Reference Type입니다. 따라서, heap 영역에 자리하게 됩니다. 이말은 기본값을 null(빈값이 아닌 할당되지 않은 값)로 초기화할 수 있다는 뜻입니다. C#의 기본 자료형은 아래 표와 같습니다. 앞으로 하나씩 알아볼 내용들이죠^^;

       타입 (형식)   할당되는 메모리 크기   기본값  데이터의 표현 범위
     논리형  bool 1byte false true, false
    정수형 byte 1byte 0 0 ~ 255
    sbyte 1byte 0 -128 ~ 127
    int 32bit 0 –2,147,483,648 ~ 2,147,483,647
    uint 32bit 0 0 ~ 4,294,967,295
    long 64bit 0 –9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
    ulong 64bit 0 0 ~ 18,446,744,073,709,551,615
    short 16bit 0 –32,768 ~ 32,767
    ushort 16bit 0 0 ~ 65,535
    실수형 decimal 16byte 0.0D ±1.0 x 10-28 ~ ±7.9228 x 1028
    double 8byte 0.0 ±5.0 × 10−324 ~ ±1.7 × 10308
    float 4byte 0.0F ±1.5 x 10−45 ~ ±3.4 x 1038
    문자형 char 16bit '\u0000' U+0000~U+FFFF

     

     

    문자열은 값이 텍스트인 String 형식의 개체입니다. 내부적으로 텍스트는 Char 개체의 순차적 읽기 전용 컬렉션으로 저장됩니다. 따라서 개체를 순환할 수 있는 foreach에서 char c in string과 같이 사용할수도 있습니다. C# 문자열 끝에는 null 종결 문자가 없습니다. 따라서 C# 문자열은 포함된 null 문자('\0')를 제한 없이 포함할 수 있습니다. 문자열의 Length 속성은 유니코드 문자의 수가 아니라 포함된 Char 개체의 수를 나타냅니다. 문자열에서 개별 유니코드 코드 포인트에 액세스하려면 StringInfo 개체를 사용합니다. 뭔가 어려운 용어들과 알수없는 문자들의 나열처럼 보일겁니다. 하지만, 예제를 하나씩 해나가다보면 어느순간 이해가 되는 때가 옵니다^^; 

    EGPGzQS.jpg

     

     

    문자열을 초기화하기 위한 방법은 2가지가 존재합니다. 하나는 null로 초기화하는 방법입니다. 그러나 이 방법은 그리 좋은 선택은 아닙니다. 특별히 null과 비교해야 하는 시나리오가 아니라면 empty(리터럴 표현은 ""입니다)로 초기화 하는게 좋습니다. empty로 초기화할 경우에는 NullReferenceException을 피할 수 있습니다. 비지니스 로직상 빈 문자열을 체크해야 한다면 String.IsNullOrEmpty(문자열) 메소드를 사용할 수 있습니다.

     

    문자열 개체는 한 번 만들어지면 변경할 수 없는 변경 불가능 개체입니다. 문자열을 수정하는 것처럼 보이는 모든 String 메서드 및 C# 연산자도 실제로는 새 문자열 개체로 결과를 반환합니다. 다음 예제에서 s1과 s2의 내용이 결합되어 단일 문자열이 만들어질 때, 두 원본 문자열은 변경되지 않습니다. += 연산자는 결합된 내용을 포함하는 새 문자열을 만듭니다. 새 개체는 s1 변수에 할당되고 s1에 할당되었던 원래 개체는 해당 개체에 대한 참조를 유지하는 다른 변수가 없으므로 가비지 수집을 위해 해제됩니다.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                string s1 = "안녕하세요! ";
                string s2 = "어린시인의벗입니다.";
     
                // s1과 s2를 += 연산자를 사용하여 연결합니다.            
                // 실제로 s1과 s2의 문자열을 연결한 후 새로운 문자열 객체를 만들고 할당합니다.            
                // 원래 객체인 s1에 대한 참조가 더 이상 없으므로 s1은 가비지 수집 대상에 포함되어 메모리에서 해제됩니다.            
                // 연결된 새로운 문자열 객체를 s1에 할당하게 됩니다.            
                s1 += s2;
                Console.WriteLine(s1);
                Console.ReadLine();
            }
        }
    }
    

     

     

    문자열 "수정"이 실제로는 새 문자열 생성이므로 문자열에 대한 참조를 만들 때 주의해야 합니다. 문자열에 대한 참조를 만든 다음 원래 문자열을 "수정"할 경우 해당 참조는 문자열을 수정할 때 만든 새 개체 대신 원래 개체를 계속해서 가리킵니다. 다음 코드에서는 이러한 동작을 보여 줍니다.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                string s1 = "Hello ";
                string s2 = s1;
                s1 += "World";
                System.Console.WriteLine(s2);
                Console.ReadLine();
            }
        }
    }
    

     

     

    이렇게 문자열의 경우에는 문자열이 연결될 때마다 새로운 객체를 생성하고 연결된 문자열을 다시 할당하게 됩니다. 따라서, 참조가 살아 있고 계속해서 문자열이 연결되는 로직에서는 StringBuilder를 사용하는게 더 효율적입니다. String과 StringBuilder를 이용한 성능 비교는 StringBuilder 객체에 대해서 알아볼 때 확인해 보도록 하겠습니다. 뭐 요즘은 컴퓨터들 성능이 워낙 좋아서 크게 의미가 없긴하지만요. 그리고, 이것저것 바쁘다보니 언제쯤 할지 모르겠네요^^;
     

    아무튼, String에서 +연산자를 여러번 사용해도 한번만 복사가 됩니다. 그러나 반복문인 for, foreach문 같은 경우에는 심각한 성능의 저하가 올 수 있습니다. 성능에 민감한 로직이라면 항상 StringBuilder를 이용하는게 좋겠습니다.

    다음 시간에...

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.