소프트웨어/C# & ASP.NET

c# 개념잡기 - Generic

falconer 2009. 11. 25. 19:03

1) 박싱 & 언박싱
   - 값타입 --박싱--> 참조타입
   - 참조타입 --언박싱--> 값타입
 
  ArrayList al = new ArrayList();
  al.Add(100);                        // ArrayList는 object를 저장함. 따라서 100(값타입)은 참조타입으로 box되어 저장됨
  int val = (int)al[0];               // al[0]를 int(값타입)로 사용하기 위해 unboxing됨

2) 값타입
   - 단순타입 : int, byte, char, float, decimal, bool 등
  - 열거형타입 : enum
  - 구조체타입 : struct
  - nullable 타입 : int?, double? 등

3) 참조타입
  - 클래스 타입 : object, string, class
  - 인터페이스 타입 : interface
  - 배열타입 : Array(int[], int[,] 등)
  - 델리게이트 타입 : delegate

4) Generic
   - boxing, unboxing 에 사용되는 리소스 소비 해결
  - Generic에 사용되는 타입은 일반적으로 T로 명명

  List<int> list = new List<int>();  // int 타입을 제네릭 타입 파라메터로 지정
  list.Add(100);                     // int 데이타만 저장가능
  int val2 = list[0];                // int 타입이기에 형변환 필요없음

5) Generic 제한사항
   - 제네릭 적용 클래스는 ContextBoundObject 클래스로 파생될 수 없음 : 런타임 오류발생
  - 제네릭은 열거형에 사용못함
  - 제네릭은 Reflection을 이용해 생성되는 동적메소드에 사용못함.

6) Generic 제약사항
   - 제네릭이 클래스레벨에서 지정될때 where로 제약을 지정할 수 있음

7) .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




001.using System;
002.using System.Collections;
003.using System.Collections.Generic;
004.  
005.namespace GenericTest
006.{
007.    class Program
008.    {
009.        static void Main(string[] args)
010.        {
011.            // 박싱 & 언박싱------------------
012.            // boxing & unboxing 발생함
013.            ArrayList al = new ArrayList();
014.            al.Add(1);                         // ArrayList는 object를 저장함. 따라서 100(값타입)은 참조타입으로 box되어 저장됨
015.            int val = (int)al[0];              // al[0]를 int(값타입)로 사용하기 위해 unboxing됨
016.            Console.WriteLine(val);
017.  
018.            // boxing & unboxing 발생 안함
019.            List<int> list = new List<int>();  // int 타입을 제네릭 타입 파라메터로 지정
020.            list.Add(2);                       // int 데이타만 저장가능
021.            int val2 = list[0];                // int 타입이기에 형변환 필요없음
022.            Console.WriteLine(val2);
023.  
024.  
025.            // 제네릭 선언------------------
026.            // class를 제네릭으로 선언
027.            GenericDeclare1<int> gd = new GenericDeclare1<int>();
028.            gd.GenericProperty = 3;
029.            Console.WriteLine(gd.GenericProperty);
030.  
031.            // method를 제네릭으로 선언
032.            GenericDeclare2 gd2 = new GenericDeclare2();
033.            Console.WriteLine(gd2.GenericMethod<int>(4));
034.  
035.  
036.            // class를 제네릭으로 선언 - where 제약------------------
037.            //GC1<int> gc1 = new GC1<int>();  --> 오류발생 : int는 IDispose를 구현한 놈이 아님
038.            GC1<TestGC1> gc1 = new GC1<TestGC1>();
039.  
040.            //GC2<int, string> gc2 = new GC2<int, string>(); --> 오류발생 : int/string은 class/struct가 아님
041.            GC2<TestGC2Class, TestGC2Strunct> gc2 = new GC2<TestGC2Class, TestGC2Strunct>();
042.  
043.            //GC3<int> gc3 = new GC3<int>(); --> 오류발생 : int는 어쨓든 아님
044.            //GC3<TestGC3_1> gc3 = new GC3<TestGC3_1>();  --> 오류발생 : TestGC3_1 은 IDispose를 구현했지만, 생성자에 파라메터가 있음
045.            GC3<TestGC3_2> gc3 = new GC3<TestGC3_2>();
046.  
047.            // TODO : 이거 잘 모르겠다.. 나중에 수정하자
048.            GC4 gc4 = new GC4();
049.        }
050.    }
051.  
052.  
053.  
054.    #region 테스트용 클래스들
055.  
056.    class TestGC1 : IDisposable
057.    {
058.        public void Dispose()
059.        {
060.        }
061.    }
062.  
063.    class TestGC2Class
064.    {
065.    }
066.  
067.    struct TestGC2Strunct
068.    {
069.    }
070.  
071.    class TestGC3_1 : IDisposable
072.    {
073.        public TestGC3_1(int i)
074.        {
075.        }
076.  
077.        public void Dispose()
078.        {
079.        }
080.    }
081.  
082.    class TestGC3_2 : IDisposable
083.    {
084.        public TestGC3_2()
085.        {
086.        }
087.  
088.        public void Dispose()
089.        {
090.        }
091.    }
092.    #endregion
093.  
094.  
095.  
096.    /// <summary>
097.    /// class를 제네릭으로 선언
098.    /// </summary>
099.    class GenericDeclare1<T1>
100.    {
101.        private T1 val;
102.  
103.        public T1 GenericProperty
104.        {
105.            get { return val; }
106.            set { this.val = value; }
107.        }
108.    }
109.  
110.    class GenericDeclare2
111.    {
112.        /// <summary>
113.        /// 메소드를 제네릭으로 선언
114.        /// </summary>
115.        public T2 GenericMethod<T2>(T2 arg)
116.        {
117.            return arg;
118.        }
119.    }
120.  
121.  
122.  
123.  
124.    #region Class를 제네릭으로 구현시 where로 제약하는 예제
125.    /// <summary>
126.    /// T는 IDisposable 인터페이스를 구현해야함
127.    /// </summary>
128.    class GC1<T>
129.        where T : IDisposable
130.    {
131.    }
132.  
133.    /// <summary>
134.    /// T는 클래스여야함
135.    /// U는 구조체여야함
136.    /// </summary>
137.    class GC2<T, U>
138.        where T : class
139.        where U : struct
140.    {
141.    }
142.  
143.    /// <summary>
144.    /// T는 IComparable을 구현해야하고
145.    /// 파라메터가 없는 - "new()" - 기본 생성자를 가진 T 이다
146.    /// </summary>
147.    class GC3<T>
148.        where T : IDisposable, new()
149.    {
150.    }
151.  
152.    /// <summary>
153.    /// 델리게이트에 파라미터가 없는 - "new()" - 기본생성자를 가진 T
154.    /// </summary>
155.    class GC4
156.    {
157.        delegate T GenericDelegate<T>(T val) where T : new();
158.        //delegate int GenericDelegate2(int val);
159.    }
160.    #endregion
161.}


출처 : http://kimstar.pe.kr/blog/100