C# 교제 수업 11. 일반화 프로그래밍

김동현·2022년 8월 12일
0

일반화 프로그래밍이란?

일반화 : 특수한 개념(사람, 돼지, 오리너구리, 고래들의 수유 방식)으로부터 공통된 개념(포유류)을 찾아 묶는 것

일반화 프로그래밍이 : 같은 동작을 하지만 다양한 형식의 동작이 필요한 경우 모든 경우의 수에
오버로딩을 할 수 없으므로 특수한 형식을 일반화 하여 만든 것이 일반화 프로그래밍 이다.

일반화 메소드

한정자 반환_형식 메소드 이름<형식_매개변수> (매개변수_목록)
{
    // ..~~
}
// int 버전
void CopyArray (int[] source, int [] target)
{
    for (int i = 0; i < source.Length; i++)
    {
        target[i] = source[i];
    }
}

// string 버전
void CopyArray (string[] source, string [] target)
{
    for (int i = 0; i < source.Length; i++)
    {
        target[i] = source[i];
    }
}

위와 같이 무한 오버로딩을 할 수 없으므로

void CopyArray<T> (T[] source, T[] target)
{
    for (int i = 0; i < source.Length; i++)
    {
        target[i] = source[i];
    }
}

로 될 수 있다.

<T> : 형식_매개변수

일반화 클래스

class 클래스이름 <형식_매개변수>
{
    // ..~~
}

기능이 같은 클래스 이지만 내부적으로 사용하는 데이터 형식이 다를 때 일반화 클래스를 이용하여 코드개선을 수 있다

class Array_Int
{
    private int[] array;

    public int GetElement(int index)
    {
        return array[index]
    }
}

class Array_Doble
{
    private Doble[] array;

    public Doble GetElement(int index)
    {
        return array[index]
    }
}

일반화 후

class Array_Genereic<T>
{
    private T[] array;

    public T GetElement(int index)
    {
        return array[index]
    }
}

사용법

Array_Generic<T> intArr = new Array_Genereic<int>();
Array_GenericK<Doble> dblArr = new Array_Generic<Double>();

형식 매개변수 제약시키기

일반화 메소드나 일반화 클래스가 입력받는 형식메게변수 T는 "모든" 데이터 형식을 대신할 수 있습니다

여기에 제약을 줄 수 있습니다.

  • where T : struct => T는 값 형식이어야 합니다.
  • where T : class => T는 참조 형식이어야 합니다.
  • where T : new() => T는 반드시 매개변수가 없는 생성자가 있어야 합니다.
  • where T : 기반클래스이름 => T는 명시한 기반 클래스의 파생 클래스여야 합니다.
  • where T : 인터페이스이름 => T는 명시한 인터페이스를 반드시 구현해야 합니다. 인터페이스이름에는 여러 개의 인터페이스를 명시할 수도 있습니다.
  • where T : U => T는 또 다른 형식 매개변수 U로부터 상속받는 클래스여야 합니다.

일반화 컬렉션

일반화 컬렉션은 컴파일 할 때 컬렉션에서 사용할 형식이 결정되고 형식 변환을 일으키지 않습니다.

List<T>
형식 매개변수에 입력한 형식 외에는 입력을 허용하지 않습니다.

using System;
using System.Collections.Generic;

namespace UsingGenericList
{
    class MainApp
    {
        static void Main(string[] args)
        {
            List<int> list = new List<int>();
            for (int i = 0; i < 5; i++)
            {
                list.Add(i);
            }
            // list : { 0, 1, 2, 3, 4 } 


            list.RemoveAt(2);
            // list : { 0, 1, 3, 4 }


            list.Insert(2, 2);
            // list : { 0, 1, 2, 3, 4 }

        }
    }
}

Queue<T>
형식 매개변수에 입력한 형식 외에는 입력을 허용하지 않습니다.

using System;
using System.Collections.Generic;

namespace UsingGenericQueue
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Queue<int> queue = new Queue<int>();

            queue.Enqueue(1);
            // queue : { 1 }
            queue.Enqueue(2);
            // queue : { 1, 2 }
            queue.Enqueue(3);
            // queue : { 1, 2, 3 }
            queue.Enqueue(4);
            // queue : { 1, 2, 3, 4 }
            queue.Enqueue(5);
            // queue : { 1, 2, 3, 4, 5 }
            queue.Dequeue();
            // queue : { 2, 3, 4, 5 }
            queue.Dequeue();
            // queue : { 3, 4, 5 }

            Console.WriteLine(queue.Count);
        }
    }
}

Stack<T>
형식 매개변수에 입력한 형식 외에는 입력을 허용하지 않습니다.

using System;
using System.Collections.Generic;

namespace UsingGenericStack
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Stack<int> stack = new Stack<int>();

            stack.Push(1);
            stack.Push(2);
            stack.Push(3);
            stack.Push(4);
            stack.Push(5);

            while (stack.Count > 0)
                Console.WriteLine(stack.Pop());
            // stack : { 5, 4, 3, 2, 1 }
        }
    }
}

Dictionary<Tkey, TValue>
TKey는 Key를 TValue는 Value를 위한 형식

using System;
using System.Collections.Generic;

namespace UsingGenericDictionary
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();

            dic["하나"] = "one";
            dic["둘"] = "two";
            dic["셋"] = "three";
            dic["넷"] = "four";
            dic["다섯"] = "five";

            Console.WriteLine(dic["하나"]);
            Console.WriteLine(dic["둘"]);
            Console.WriteLine(dic["셋"]);
            Console.WriteLine(dic["넷"]);
            Console.WriteLine(dic["다섯"]);

            // one
            // two
            // three
            // four
            // five
        }
    }
}

foreach를 사용할 수 있는 일반화 클래스

  • IEnumerator GetEnumerator() : IEnumerator 형식의 객체를 반환 (IEnumerable로부터 상속받은 메소드)

  • IEnumerator<T> GetEnumerator() : IEnumerator<T> 형식의 객체를 반환

  • IEnumerator<T> 의 메소드와 프로퍼티

    • boolean MoveNext() : 다음 요소로 이동합니다. 컬렉션의 끝을 지난 경우에는 false, 이동이 성공한 경우에는 true를 반환합니다.
    • void Reset() : 컬렉션의 첫 번째 위치의 "앞"으로 이동합니다. 첫 번째 위치가 0번일 때, Reset()을 호출하면 -1번으로 이동하는 것이죠. 첫 번째 위치로의 이동은 MoveNext()를 호출한 다음에 이루어집니다.
    • Object Current { get; } : 컬렉션의 현재 요소를 반환합니다(IEnumerator로부터 상속받은 프로퍼티)
    • T Current { get; } : 컬렉션의 현재 요소를 반환합니다.
profile
해보자요

0개의 댓글