7. 형식변환

C#/과제 2019. 3. 26. 02:19

형식변환

우리가 공부하는 C#에는 각종 데이터 타입이 존재한다. 값형식의 int, double, float, 참조형식의 class, string 등등...

어떠한 변수에 값을 담을 때 우리는 들어올 값을 예측하고 그 값의 형식에 따라 변수의 데이터 타입을 지정한다.


예를 들어 integer 타입 6과목의 시험점수를 입력받았다고 가정해보자.

그럼 이 6과목의 평균은 딱 맞게도 integer 타입에 맞게 정수일 수도 있고, 타입과 다르게 소수일 수도 있다.

이러한 경우에는 어떻게 해야할까?

int average = (a+b+c+d+e+f)/6; 을 했을 때 과연 오류가 단 한번도 안날까?

이러한 경우에 사용하는 것이 형식변환이다.


-형식변환에는 특수구문이 필요하지 않은 [암시적 변환], 캐스트 연산자를 통한 [명시적 변환].

 변환 연산자를 이용한 [사용자 정의 변환], 도우미 클래스를 활용한 [도우미 클래스 이용 변환]이 있다.


-암시적 변환은 a에서 b라는 데이터타입으로 변환할 때, 데이터 손실이 없을 경우 가능하다.

 추가적인 연산자가 없어도 데이터의 손실이 없기 때문에 별 오류가 없이 컴파일이 되는 것이다.

 ex) int(32비트 정수)타입의 값을 long(64비트 정수)타입의 변수에 넣는다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int num = 1000;
            long longNum = num;
        }
    }
}
cs
     위의 예제에서 num은 32비트 정수형인 int 데이터타입이고,

 longNum은 64비트 정수형인 long 데이터타입이기 때문에 암시적 변환이 가능하다.


-명시적 변환은 변환을 수행할 때 데이터의 손실될 수 있을 때, 캐스트라는 것을 이용해 명시해주고 변환하는 것을 뜻한다.

 이는 컴파일러가 손실이 예상되는 경우 오류를 리턴하면서 컴파일이 되지 않는다. 이를 캐스트를 통해 개발자가 인지함을 명시하고 변환하는 것이다.

위의 예제를 보면 알 수 있다. 64비트 데이터타입 double을 32비트 데이터타입 integer형에 대입할 경우 변활할 수 없다는 경고문이 출력된다.

이를 아래와 같이 (int)라는 캐스트를 이용해 명시해줄 경우

아무런 경고문이 출력되지 않는다. 이는 double형 num의 값인 1.55를 정수형 integerNum에 대입하는 과정에서

0.55가 손실되는 것을 인지하고 있다는 것을 (int)라는 캐스트를 통해 명시를 해줬기 때문이다.

그럼 integerNum에는 double형 num의 값인 1.55에서 0.55가 손실되고 1이 대입이 되므로 출력하면 위와 같은 결과를 나타낸다.



이 암시적 변환과 명시적 변환은 클래스 간에도 적용이 된다.

예를 들어 Mother Class와 Child Class가 있다. Child Class는 Mother Class를 상속한다.

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class Mother
{
    public int age = 10;
    public Mother()
    {
        Console.WriteLine("부모생성자 호출");
    }
}
class Child : Mother
{
    public string name = "자식";
    public Child()
    {
        Console.WriteLine("자식생성자 호출");
    }
}
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Mother M = new Child();
        }
    }
}
cs
Child Class는 Mother Class를 상속하므로 기본적으로 age라는 10의 값을 가진 integer형 변수를 가지고 있다.

Mother라는 기본 클래스가 자신을 상속한 Child Class를 가리킬 때는 손실되는 데이터가 없으므로 암시적 변환이 가능하다. (Mother M = new Child();)

기본적으로 상속받은 클래스는 부모클래스의 멤버 변수와 메서드를 상속받고, 추가 적인 멤버 변수와 메서드를 지니기 때문이다.



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
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class Mother
{
    private int age = 10;
    public Mother()
    {
        
        Console.WriteLine("부모생성자 호출");
    }
}
class Child : Mother
{
    public string name = "자식";
    public Child()
    {
        Console.WriteLine("자식생성자 호출");
    }
}
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Mother M = new Child();
            Child C = new Mother();
        }
    }
}

cs

이 예제는 오류가 난다. 왜 날까?

바로 Child Class는 위의 예시처럼 Mother Class를 상속했고, Mother Class의 멤버 변수인 age외에도 다른 변수인 name이 있기 때문이다.

그 말인 즉슨 상속받은 클래스가 상속하는 클래스로 변환을 할 때 암시적 변환이 불가능하다는 것이다.

왜? 바로 위에서 확인했듯, 데이터가 손실될 수 있기 때문이다. 그럼 이 것을 변환하려면 어떻게 해야할까?



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
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class Mother
{
    private int age = 10;
    public Mother()
    {
        
        Console.WriteLine("부모생성자 호출");
    }
}
class Child : Mother
{
    public string name = "자식";
    public Child()
    {
        Console.WriteLine("자식생성자 호출");
    }
}
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Mother M = new Child();
            Child C = (Child)new Mother();
        }
    }
}
cs
이렇게! (Child)라는 캐스트를 new Mother();앞에 명시해줌으로서 명시적 변환이 가능해진다.



※사용자 정의 변환과 도우미 클래스 이용 변환은 추가 예정


참조

Microsoft Docs

https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/types/casting-and-type-conversions (캐스팅 및 형식변환)

https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/statements-expressions-operators/using-conversion-operators

(변환 연산자 사용)

https://docs.microsoft.com/ko-kr/dotnet/csharp/tutorials/inheritance (C# 및 .NET의 상속)




'C# > 과제' 카테고리의 다른 글

9. WoW캐릭터 만들기 [~ing .0326]  (0) 2019.03.26
8. 멤버변수와 지역변수  (0) 2019.03.26
6. using  (0) 2019.03.26
5. Stack과 Heap  (0) 2019.03.25
4. 문자열 표현식  (0) 2019.03.25
: