박싱 & 언박싱
값타입 –박싱–> 참조타입
참조타입 –언박싱–> 값타입
ArrayList al = new ArrayList();
al.Add(100); // ArrayList는 object를 저장함. 따라서 100(값타입)은 참조타입으로 box되어 저장됨
int val = (int)al[0]; // al[0]를 int(값타입)로 사용하기 위해 unboxing됨 값타입
단순타입 : int, byte, char, float, decimal, bool 등
열거형타입 : enum
구조체타입 : struct
nullable 타입 : int?, double? 등
참조타입
클래스 타입 : object, string, class
인터페이스 타입 : interface
배열타입 : Array(int[], int[,] 등)
델리게이트 타입 : delegate
Generic
boxing, unboxing 에 사용되는 리소스 소비 해결
Generic에 사용되는 타입은 일반적으로 T로 명명
List<int> list = new List<int>(); // int 타입을 제네릭 타입 파라메터로 지정
list.Add(100); // int 데이타만 저장가능
int val2 = list[0]; // int 타입이기에 형변환 필요없음 Generic 제한사항
제네릭 적용 클래스는 ContextBoundObject 클래스로 파생될 수 없음 : 런타임 오류발생
제네릭은 열거형에 사용못함
제네릭은 Reflection을 이용해 생성되는 동적메소드에 사용못함.
Generic 제약사항
제네릭이 클래스레벨에서 지정될때 where로 제약을 지정할 수 있음
.Net Framework에서 제공하는 Generic
Dictionary<TKey, TValue> : Hashtable의 제네릭 버전. Key & Value가 한쌍. Key는 유일
List<T> : ArrayList의 제네릭 버전. 배열의 크기를 동적으로 구성
SortedList<TKey, TValue> : Dictionary + List. Key & Value가 한쌍. 동적 배열. Key값으로 정렬됨.
LinkedList<T> : 새로생김.
Queue<T> : Queue의 제네릭 버전
Stack<T> : Stack의 제네릭 버전
타입 제네릭 비제네릭 제네릭 네임스페이스 클래스 List<T> ArrayList System.Collections.Generic Dictonary<TKey, TValue> HashTable SortedList<TKey, TValue> SortedList Stack<T> Stack Queue<T> Queue LinkedList<T> – ReadOnlyCollection<T> – System.Collections.ObjectModel KeyedCollection<TKey, TValue> – 인터페이스 IList<T> IList System.Collections.Generic IDictonary<TKey, TValue> IDictonary ICollection<T> ICollection IEumerator<T> IEumerator IEumerable<T> IEumerable IComparer<T> IComparer IComparable<T> IComparable
using System;
using System.Collections;
using System.Collections.Generic;
namespace GenericTest
{
class Program
{
static void Main(string[] args)
{
// 박싱 & 언박싱------------------
// boxing & unboxing 발생함
ArrayList al = new ArrayList();
al.Add(1); // ArrayList는 object를 저장함. 따라서 100(값타입)은 참조타입으로 box되어 저장됨
int val = (int)al[0]; // al[0]를 int(값타입)로 사용하기 위해 unboxing됨
Console.WriteLine(val);
// boxing & unboxing 발생 안함
List<int> list = new List<int>(); // int 타입을 제네릭 타입 파라메터로 지정
list.Add(2); // int 데이타만 저장가능
int val2 = list[0]; // int 타입이기에 형변환 필요없음
Console.WriteLine(val2);
// 제네릭 선언------------------
// class를 제네릭으로 선언
GenericDeclare1<int> gd = new GenericDeclare1<int>();
gd.GenericProperty = 3;
Console.WriteLine(gd.GenericProperty);
// method를 제네릭으로 선언
GenericDeclare2 gd2 = new GenericDeclare2();
Console.WriteLine(gd2.GenericMethod<int>(4));
// class를 제네릭으로 선언 - where 제약------------------
//GC1<int> gc1 = new GC1<int>(); --> 오류발생 : int는 IDispose를 구현한 놈이 아님
GC1<TestGC1> gc1 = new GC1<TestGC1>();
//GC2<int, string> gc2 = new GC2<int, string>(); --> 오류발생 : int/string은 class/struct가 아님
GC2<TestGC2Class, TestGC2Strunct> gc2 = new GC2<TestGC2Class, TestGC2Strunct>();
//GC3<int> gc3 = new GC3<int>(); --> 오류발생 : int는 어쨓든 아님
//GC3<TestGC3_1> gc3 = new GC3<TestGC3_1>(); --> 오류발생 : TestGC3_1 은 IDispose를 구현했지만, 생성자에 파라메터가 있음
GC3<TestGC3_2> gc3 = new GC3<TestGC3_2>();
// TODO : 이거 잘 모르겠다.. 나중에 수정하자
GC4 gc4 = new GC4();
}
}
#region 테스트용 클래스들
class TestGC1 : IDisposable
{
public void Dispose()
{
}
}
class TestGC2Class
{
}
struct TestGC2Strunct
{
}
class TestGC3_1 : IDisposable
{
public TestGC3_1(int i)
{
}
public void Dispose()
{
}
}
class TestGC3_2 : IDisposable
{
public TestGC3_2()
{
}
public void Dispose()
{
}
}
#endregion
/// <summary>
/// class를 제네릭으로 선언
/// </summary>
class GenericDeclare1<T1>
{
private T1 val;
public T1 GenericProperty
{
get { return val; }
set { this.val = value; }
}
}
class GenericDeclare2
{
/// <summary>
/// 메소드를 제네릭으로 선언
/// </summary>
public T2 GenericMethod<T2>(T2 arg)
{
return arg;
}
}
#region Class를 제네릭으로 구현시 where로 제약하는 예제
/// <summary>
/// T는 IDisposable 인터페이스를 구현해야함
/// </summary>
class GC1<T>
where T : IDisposable
{
}
/// <summary>
/// T는 클래스여야함
/// U는 구조체여야함
/// </summary>
class GC2<T, U>
where T : class
where U : struct
{
}
/// <summary>
/// T는 IComparable을 구현해야하고
/// 파라메터가 없는 - "new()" - 기본 생성자를 가진 T 이다
/// </summary>
class GC3<T>
where T : IDisposable, new()
{
}
/// <summary>
/// 델리게이트에 파라미터가 없는 - "new()" - 기본생성자를 가진 T
/// </summary>
class GC4
{
delegate T GenericDelegate<T>(T val) where T : new();
//delegate int GenericDelegate2(int val);
}
#endregion
}