10 장 . 참조형
description
Transcript of 10 장 . 참조형
C#10 장 . 참조형
c#
10 장 . 참조형
2 / 24
• 참조형의 주요한 특징을 이해하고 응용해서 사용한다
• 서로 다른 형식 사이의 형 변환의 가능성을 결정할 수 있다
• 참조형 사이의 데이터 형 변환을 이해할 수 있다
• 값형과 참조형 사이의 박싱과 언박싱 변환을 이해하고 변환할 수 있다 .
학습 목표
c#
10 장 . 참조형
3 / 24
목차1. 참조형 변수2. 데이터 형 변환
c#
10 장 . 참조형
4 / 24
1. 참조형 변수
참조형 변수
- 변수는 스택 영역에 저장
- 실제 데이터는 메모리의 힙 영역에 저장
클래스도 일종의 참조형으로 분류된다 .클래스를 인스턴스화 해서 변수에 할당
== 참조형 변수 선언과 같다 .
c#
10 장 . 참조형
5 / 24
1. 참조형 변수
참조형 변수의 선언과 해제변수는 스택영역에 저장되고 , 실제 데이터는 힙영역에 저장된다 . 스택에 저장되는 값은 실제 데이터가 저장된 힙영역의 주소값이다 . 메모리의 해제 방법은 참조형 변수에 null 을 할당하면 된다 .
< 참조형 선언및 멤버 접근 예제 >class Coordinate{
public int x = 0 ;}…Coordinate c = new Coordinate() ;
c.x = 1;
< 참조형 메모리해제 예제 >Coordinate c = new Coordinate() ;
c = null ;
참조형 변수선언 및 메모리할당참조형 변수 c 를 선언하고 실제 데이터가
저장될 힙 영역의 메모리 확보는 new 키워드를 통해서 이루어 지며 , 생성자(Coordinate()) 를 통해서 초기화된다 .
참조형의 메모리 해제null 을 참조형 변수에 할당하면 확보되어
있던 메모리가 해제된다 .
c#
10 장 . 참조형
6 / 24
1. 참조형 변수
참조형 변수 예제
1. using System;
2. class Coordinate3. {4. public int x;5. public int y;6. }
7. class ConsoleApplication8. {9. static void Main(string[] args)10. {11. Coordinate c = new Coordinate();12. // 참조형 변수 선언 및 메모리 할당
13. c.x = 1;14. c.y = 2;15. // 참조형 변수의 멤버 접근16. Console.WriteLine("c = {0}, {1}", c.x, c.y);17. }18.}
(11 행 ) 객체 생성 측면에서 Cordinate 클래스로 변수 c 를 선언 후 new 키워드를 사용해서 객체 선언
클래스를 데이터형 측면으로 보면 , Cordinate 형 변수 c 를 선언하고 힙 영역의 메모리를 할당
즉 , 객체 생성은 데이터형의 선언 , 메모리 확보와 같다 .
c#
10 장 . 참조형
7 / 24
1. 참조형 변수
값형과 참조형의 비교값형의 경우 == 와 != 의 연산자로 값을 비교한다 .참조형의 값은 == 와 != 로 비교할 수 없다 .== 혹은 != 연산자는 단지 참조형 변수의 힙영역 주소값 만을 비교하게 된다 .
< 예제 >class Coordinate{
public int x ;}…Coordinate c1 = new Coordinate();Coordinate c2 = new Coordinate();
c1.x = 1 ;c2.x = 1 ;
if(c1= = c2) Console.WriteLine(“c1==c2”);
elseConsole.WriteLine(“c1!=c2”);
두 객체의 멤버에 같은 값을 할당한다 .
두 객체의 저장된 값은 같으나 참조형 데이터 값은
== 연산자로 비교할 수 없다 . 굳이 비교를 하게 되면 서로 다른 값으로 인식한다 .
c#
10 장 . 참조형
8 / 24
1. 참조형 변수
값형과 참조형 변수 ( 주소 ) 비교 예제1. using System;
2. class Coordinate3. {4. public int x;5. public int y;6. }
7. class ConsoleApplication8. {9. static void Main(string[] args)10. {11. Coordinate c1 = new Coordinate();12. Coordinate c2 = new Coordinate();
13. c1.x = 1;14. c1.y = 2;15. c2.x = 1;16. c2.y = 2;
17. Console.WriteLine("c1 = {0}, {1}", c1.x, c1.y);18. Console.WriteLine("c2 = {0}, {1}", c2.x, c2.y);
19. if (c1 == c2) // 참조형 변수 비교20. Console.WriteLine("c1 == c2");21. else22. Console.WriteLine("c1 != c2");23. }24.}
c#
10 장 . 참조형
9 / 24
1. 참조형 변수
값형과 참조형 값 ( 실제 값 ) 비교 예제using System;
class Coordinate{ public int x; public int y;}
class ConsoleApplication{ static void Main(string[] args) { Coordinate c1 = new Coordinate(); Coordinate c2 = new Coordinate();
c1.x = 1; c1.y = 2; c2.x = 1; c2.y = 2;
Console.WriteLine("c1.x c1.y = {0}, {1}", c1.x, c1.y); Console.WriteLine("c2.x c2.y = {0}, {1}", c2.x, c2.y);
if (c1.x == c2.x) // 참조형 값 비교 Console.WriteLine("c1.x == c2.x"); else Console.WriteLine("c1.x != c2.x"); }}
c#
10 장 . 참조형
10 / 24
1. 참조형 변수
같은 객체에 대한 다중 참조 ( 참조형 변수 복사 : 주소 복사 )1. using System;
2. class Coordinate3. {4. public int x;5. public int y;6. }
7. class ConsoleApplication8. {9. static void Main(string[] args)10. {11. Coordinate c1 = new Coordinate();12. Coordinate c2; //Coordinate 형 변수 c2 선언
13. c1.x = 1;14. c1.y = 2;
15. c2 = c1; // 복사
16. Console.WriteLine("c1.x, c1.y = {0}, {1}", c1.x, c1.y);17. Console.WriteLine("c2.x, c2.y = {0}, {1}", c2.x, c2.y);
18. if (c1 == c2) // 참조형 변수 비교 ( 주소 비교 )19. Console.WriteLine("c1 == c2");20. else21. Console.WriteLine("c1 != c2");22. }23.}
스택영역 힙영역
c1c2
1 2x y
(15 행 ) c1 이 가리키는 주소를 c2 에 복사함
c#
10 장 . 참조형
11 / 24
1. 참조형 변수
같은 객체에 대한 다중 참조 ( 참조형 데이터 변경 )1. using System;
2. class Coordinate3. {4. public int x;5. public int y;6. }
7. class ConsoleApplication8. {9. static void Main(string[] args)10. {11. Coordinate c1 = new Coordinate();12. Coordinate c2;
13. c1.x = 1;14. c1.y = 2;
15. c2 = c1;16. Console.WriteLine("c1.x, c1.y = {0}, {1}", c1.x, c1.y);17. Console.WriteLine("c2.x, c2.y = {0}, {1}", c2.x, c2.y);
18. c2.x = 10; // 멤버의 값 변경 19. c2.y = 20;
20. Console.WriteLine("c1.x, c1.y = {0}, {1}", c1.x, c1.y);21. Console.WriteLine("c2.x, c2.y = {0}, {1}", c2.x, c2.y);
22. }23.}
C1 과 C2 는 같은 곳을 참조 하므로x,y 의 값을 변경 후 결과 값은 같다 .
c#
10 장 . 참조형
12 / 24
2. 데이터 형 변환
기반클래스와 파생 클래스형 간의 형 변환
파생클래스 -> 기반클래스로의 변환은 암시적 가능
기반클래스 -> 파생클래스로의 변환은 명시적으로 변환해야 가능
데이터 호환이 되지 않을 때는 InvalidCastException 발생
< 예제 >class Vehicle{}class Car : Vehicle{}…
Vehicle veh = new Vehicle();Car car = new Car();
Vehicle a = car ;
Car b = (Car) a ;
파생 클래스형을 기반 클래스형으로 형 변환
암시적으로 형 변환됨
기반 클래스형을 파생 클래스형으로 형 변환
명시적으로 형 변환해야 함
c#
10 장 . 참조형
13 / 24
2. 데이터 형 변환
참조형 데이터 형 변환1. using System;2. class Vehicle3. {4. }5. class Car : Vehicle6. {7. }8. class ConsoleApplication9. {10. static void Main(string[] args)11. {12. Vehicle vehicle = new Vehicle();
// 기반 클래스인 Vehicle 형 변수 vehicle 선언 및 객체 생성13. Car car = new Car();
//v 파생 클래스인 Car 형 변수 car 를 선언 및 객체 생성14. Vehicle a = car; // Child to Parent 형 변환
// a : Vehicle 형 변수 , car : Car 형 변수 // 암시적 형변환이 이루어짐 : car 가 대입되기 전에 Vehicle 형으로
15. Car b = (Car)a; // Parent to Child 형 변환16. }17.}
(14 행 ) : 파생에서 기반으로 변환하는 명시적 형 변환(15 행 ) : 기반에서 파생으로 변환하는 암시적 형 변환
c#
10 장 . 참조형
14 / 24
2. 데이터 형 변환
참조형 데이터 형 변환
1. using System;
2. class Vehicle3. {4. }
5. class Car : Vehicle6. {7. }
8. class ConsoleApplication9. {10. static void Main(string[] args)11. {12. Vehicle vehicle = new Vehicle();13. Car car = new Car();
14. Vehicle a = car; // Child to Parent 형변환15. Car b = a; // Parent to Child 형변환16. //Car b = (Car)a; // Parent to Child 형변환17. }18.}
(15 행 ) 형 변환 없이 복사 ( 대입 ) 시 : 에러 발생
c#
10 장 . 참조형
15 / 24
2. 데이터 형 변환
참조형 데이터 형 변환1. using System;2. class Vehicle3. { }4. class Car : Vehicle5. { }6. class ConsoleApplication7. {8. static void Main(string[] args)9. {10. Vehicle vehicle = new Vehicle();11. Car car = new Car();
12. Vehicle a = car; // Child to Parent 형변환13. try14. {15. Car b = (Car)a; // Parent to Child 형변환16. Console.WriteLine("Vehicle 이 Car 로 형 변환 ");17. }18. catch (InvalidCastException e)19. {20. Console.WriteLine(e.Message);21. }22. }23.}
(15 행 ) 실행할 때 캐스트 연산자가 데이터 형을 확인한다 . 이때
데이터 호환이 되지 않는다면 예외를 발생 시킨다 . 발생하는
예외는 InvalidCastException 이다 .앞의 예에서 try … catch 문을 추가해서 예외 처리를 했다 .
c#
10 장 . 참조형
16 / 24
2. 데이터 형 변환
is 연산자
참조형 사이의 형 변환을 하고자 할 때 데이터 형이 다르면 Invalid-CastException 을 이용해서 예외 처리를 했지만 is 연산자를
사용하면 예외 상황을 비켜가게 할 수도 있다 .
is 연산자는 형 변환을 하지 않고 객체의 데이터 형을 테스트 하는데
유용하다 .
c#
10 장 . 참조형
17 / 24
2. 데이터 형 변환
is 연산자
데이터 형 사이의 호환성을 테스트하는 데 사용
< 예제 >class Vehicle{}class Car : Vehicle{}…
Vehicle veh = new Vehicle();Car car = new Car();
if( car is Vehicle){
…}else
…
car 참조형 변수가 Vehicle형과 호환 가능한 형태인지 조사
호환가능하면 true, 호환가능하지 않으면 false
return
c#
10 장 . 참조형
18 / 24
2. 데이터 형 변환
is 연산자의 사용
using System;class Vehicle{}
class Car : Vehicle{}
class ConsoleApplication{ static void Main(string[] args) { Vehicle vehicle = new Vehicle(); Car car = new Car();
// is 연산자 if (car is Vehicle) { vehicle = car; // 형이 같으면 변환 없이 대입 가능 Console.WriteLine("Car is a Vehicle"); } else { Console.WriteLine("Car is not a Vehicle"); } }}
c#
10 장 . 참조형
19 / 24
2. 데이터 형 변환
as 연산자
as 연산자는 괄호 안에 데이터형을 표현하는 캐스트 연산자와 비슷한
역할을 한다 .
as 연산자는 서로 간의 형식을 비교해서 형 변환이 가능한지를 검사한 후
형 변환이 가능하면 형 변환된 값을 반환한다 .
c#
10 장 . 참조형
20 / 24
2. 데이터 형 변환
as 연산자
캐스트 연산과 비슷
형변환이 가능한 형인지 호환성 조사 후에 형 변환된 값 반환
참조형 변수 car 를 Vehicle형으로 변환
형 변환 가능한지 호환성 검사 후에 변환된 값을 넘긴다 . 만약 형 변환이 가능치 않으면 null 을
반환하고 예외를 발생시키지 않는다 .
< 예제 >class Vehicle{}class Car : Vehicle{}…
Vehicle veh = new Vehicle();Car car = new Car();
veh = car as Vehicle ;
c#
10 장 . 참조형
21 / 24
2. 데이터 형 변환
as 연산자
using System; class Vehicle{ }
class Car : Vehicle{}class ConsoleApplication{ static void Main(string[] args) { Vehicle vehicle = new Vehicle(); Car car = new Car();
// 1. as 연산자 사용하여 형 변환 vehicle = car as Vehicle; //Car 형 변수 car 를 as 연산자를 사용해서 Vehicle 형으로 변환
if (vehicle != null) // 2. 형 변환 성공 여부 확인 { Console.WriteLine("Car is a Vehicle"); } else { Console.WriteLine("Car is not a Vehicle"); } }}
1. Vehicle 형 변수 vehicle 선언2. new 연산자 이용하여 변수명이 vehicle
인 객체를 생성3. Vehicle() 생성자를 이용하여 변수명이
vehicle 인 객체를 초기화
c#
10 장 . 참조형
22 / 24
2. 데이터 형 변환
object 형 변환모든 참조형은 System.Object 형으로부터 파생되어 나왔다 . 따라서 모든 참조형은 System.Object 형으로 형 변환이 가능하다 .
1. using System;2. class Vehicle { }3. class Car : Vehicle{ }4. class ConsoleApplication5. {6. static void Main(string[] args)7. {8. Vehicle v = new Vehicle();9. Car c = new Car();
10. // object11. object o = c;12. Car b = o as Car;
13. if (b != null)14. { Console.WriteLine("Vehicle is a Car"); }15. else16. { Console.WriteLine("Vehicle is not a Car");17. }18. }19.}
(11 행 ) Car 형 변수 c 를 object 형으로 암시적으로 변환함
(12 행 ) object 형으로 변환된 변수 o 를 Car형으로 명시적으로 변환함 .
즉 , object 형은 모든 객체의 최상위 기반 클래스 형이므로 형 변환이 가능하다 .
c#
10 장 . 참조형
23 / 24
2. 데이터 형 변환
박싱과 언박싱
C# 에서는 값형과 참조형 사이에서도 형 변환이 가능하다 .값형을 참조형으로 형 변환하는 것을 박싱 (Boxing), 반대로
참조형을 값형으로 형 변환하는 것을 언박싱 (Unboxing) 이라고
한다 .
c#
10 장 . 참조형
24 / 24
2. 데이터 형 변환
박싱과 언박싱
값형 -> 참조형 : 박싱 (boxing)
참조형 -> 값형 : 언박싱 (unboxing)
< 예제 >
int x = 123 ;
object o = x ;
int y = (int) o ;
박싱 (boxing)정수형 ( 값형 ) 변수 x 를 참조형
변수 o 에 할당하게 되면 암시적으로 x 는 참조형으로 형
변환되게 된다 .
언박싱 (unboxing)정수형 변수 y 에 참조형 변수를
할당하려고 하면 명시적으로 캐스팅해서 참조형을 정수형으로
변환하게 된다 .
c#
10 장 . 참조형
25 / 24
2. 데이터 형 변환
박싱과 언박싱using System;
class ConsoleApplication{ static void Main(string[] args) { int x = 123;
object o = x; // Boxing // 값형인 int 형으로 정의된 x 를 // 참조형인 object 형으로 암시적으로 변환해서 변수 o 에 복사 int y = (int)o; // Unboxing // 참조형인 변수 o 를 값형인 int 형으로 변환해서 복사
Console.WriteLine(x); Console.WriteLine(y); }}
형변환이 발생 했지만 데이터는 변하지 않음
c#
10 장 . 참조형
26 / 24
요약• 참조형 변수란 곧 객체라고 말할 수 있다 . • 참조형 변수는 메모리의 스택 영역에 저장되지만 실제
저장되는 값은 데이터가 저장된 메모리의 힙 영역의 주소 값이다 .
c#
10 장 . 참조형
27 / 24
요약• is 연산자를 통해 형 변환의 가능 여부를 알 수 있다 . is
연산자를 통해 true 를 반환하면 형 변환이 가능하고 false 면 형 변환이 가능하지 않다 .
c#
10 장 . 참조형
28 / 24
요약• 기반 클래스와 파생 클래스 관계에 있는 객체 사이에는
형 변환이 가능하다 .
• 파생 클래스형 변수는 기반 클래스형으로 변환할 때 명시적으로 변환하지 않아도 되면 내부적으로 변환한다 .
• 그렇지만 기반 클래스형 변수를 파생 클래스형으로 변환할 때는 명시적으로 형 변환을 해줘야 한다 .
c#
10 장 . 참조형
29 / 24
요약• 값형과 참조형 변수 사이에도 형 변환이 가능하다 .
• 값형을 참조형으로 변환하는 것을 박싱이라고 하며 참조형을 값형으로 변환하는 것을 언박싱이라고 한다 .