티스토리 뷰

[C#] 데이터 형변환과 캐스팅


C#은 컴파일 타임에 정적으로 데이터 형이 지정이 되므로, 변수의 형을 변환하지 않으면 다시 선언하거나 다른 형의 값에 넣는것이 불가능합니다. int형을 string형으로 변환하여 넣을 수 없습니다.


그렇다면 C#에서 변수나 매개변수의 값을 복사해야 하는 경우 어떻게 하는지 이글을 통해서 알아보도록 하겠습니다. C#에서 데이터 형을 변환하는 방법을 4가지를 제공하고 있습니다.


  • 암시적 변환: 파생클래스->기본클래스 혹은 int16->int32등 변환을 할 때 변환에 대한 안정성과 데이터 손실에 대한 리스크없이 데이터 형이 변환되는것을 의미합니다.

  • 명시적 변환(캐스트): Object -> 특정 클래스로 갈때 혹은 int32 -> int16등 변환시 값의 손실이 발생할 수 있거나 변환이 실패할 수 있는 경우 명시적 전환을 사용합니다.

  • 사용자 정의 변환: 사용자 정의 변환은 기본 클래스-파생 클래스 관계가 없는 사용자 지정 형식 간의 명시적 변환과 암시적 변환이 가능하도록 사용자가 정의할 수 있는 특수한 메서드를 통해 수행됩니다. 

  • 도우미 클래스를 사용한 변환: 정수와 System.DateTime 개체 또는 16진수 문자열과 바이트 배열과 같이 서로 호환되지 않는 형식 간에 변환하려면 Int32.Parse와 같은 기본 제공 숫자 형식의 System.BitConverter 클래스, System.Convert 클래스Parse 메서드를 사용합니다. 


1) 암시적 변환


int num = 1234;

long bigNum = num; // 동일 데이터 형의 작은 타입 -> 동일 데이터형의 큰 타입으로 암시적 변환 수행


아래의 표는 암시적 변환을 자동적으로 지원하는 타입을 표로 나타낸 그림입니다. 


아래의 소스는 파생클래스를 기본 클래스로 변환하는 코드입니다. 이 코드를 명확히 숙지하셔야 합니다. 그 이유는 Factory Method 패턴이나 Factory 패턴등 다양한 디자인 패턴에서 파생클래스를 기본 클래스로 변환하여 많이 사용하기 때문입니다. 


Derived d = new Derived();

Base b = d; // 파생 클래스에서 상속받은 클래스로의 암시적 변환 수행


2) 명시적 변환


암시적 변환은 작은 데이터형(long)을 큰 데이터 형(float or double)으로 변환하는 과정이기 때문에 값의 손실이 없습니다. 하지만 반대로의 경우에는 값을 잃을 수 있습니다. 이런 경우 명시적 변환을 사용합니다. 


int myInt = int.MaxValue;

try

{

   byte myByte = (byte)myInt;

   Console.WriteLine("The byte value is {0}.", myByte); // int to byte 명시적 형변환

}

catch (OverflowException)

{

   Console.WriteLine("Unable to convert {0} to a byte.", myInt);

}   


아래의 코드는 임의적으로 기본 클래스에 파생클래스의 객체를 생성하고 이를 다시 파생 클래스로 변환하는 과정입니다. 그 아래부분에는 d 변수가 null인지 아닌지를 판단하는 코드가 들어있습니다. 객체에 대한 명시적 변환은 변환이 실패할 수도 있기 때문에 이러한 코드가 반드시 들어가야 합니다. 변환 실패시 null값이 들어가지요 


Base a = new Derived();

Derived d = (Derived) a; // 기본 -> 파생 클래스로의 명시적 변환

if(d != null) { //나머지 코드 부분 }


3) 사용자 정의 변환

사용자 정의 변환은 Implicit와 explicit 키워드를 사용해서 정의할 수 있습니다. 

  • implicit 키워드는 암시적 사용자 정의 형식 변환 연산자를 선언하는데 사용이 됩니다.
  • explicit 키워드는 명시적 사용자 정의 형식 변환 연산자를 선언하는데 사용이 됩니다. 

아래의 코드는 implicit 키워드의 사용 예입니다.

class Digit

{

    public Digit(double d) { val = d; }

    public double val; 


    // Digit 클래스에서 Double형으로 형변환

    public static implicit operator double(Digit d)

    {

        return d.val;

    }


    //  Double 형에서 Digit 객체로 형변환

    public static implicit operator Digit(double d)

    {

        return new Digit(d);

    }

}


class Program

{

    static void Main(string[] args)

    {

        Digit dig = new Digit(7);


        // 사용자 명시적 변환 수행

        double num = dig;


        // 사용자 명시적 변환 수행

        Digit dig2 = 12;


        Console.WriteLine("num = {0} dig2 = {1}", num, dig2.val);

        Console.ReadLine();

    }

}


아래의 코드는 explicit 키워드 사용 예입니다. 


class Celsius

{

    public Celsius(float temp)

    {

        degrees = temp;

    }


    // Celsius -> Fahrenheit 사용자 명시적 변환

    public static explicit operator Fahrenheit(Celsius c)

    {

        return new Fahrenheit((9.0f / 5.0f) * c.degrees + 32);

    }


    public float Degrees

    {

        get { return degrees; }

    }


    private float degrees;

}


class Fahrenheit

{

    public Fahrenheit(float temp)

    {

        degrees = temp;

    }


    // Fahrenheit -> Celsius 사용자 명시적 변환

    public static explicit operator Celsius(Fahrenheit fahr)

    {

        return new Celsius((5.0f / 9.0f) * (fahr.degrees - 32));

    }


    public float Degrees

    {

        get { return degrees; }

    }


    private float degrees;

}


class MainClass

{

    static void Main()

    {

        Fahrenheit fahr = new Fahrenheit(100.0f);

        Console.Write("{0} Fahrenheit", fahr.Degrees);

        Celsius c = (Celsius)fahr; // 명시적 변환 수행


        Console.Write(" = {0} Celsius", c.Degrees);

        Fahrenheit fahr2 = (Fahrenheit)c; // 명시적 변환 수행

        Console.WriteLine(" = {0} Fahrenheit", fahr2.Degrees);

    }

}


이상 C#에서의 데이터 형변환과 캐스팅 방법에 대해서 알아보았습니다.


이글이 도움이 되셨나요?

그렇다면 아래의 그림을 클릭해주세요.


댓글