C# 제네릭(제네릭스)

제네릭(제네릭스)



다양한 유형에 해당하는 함수(또는 클래스)를 정의할 수 있습니다.

예를 들어, 다음과 같은 함수가 있다고 가정합니다.
Int32 score = 5;
Int32 old_score = 3;

public static Int32 GetHighestScore()
{
    return (score > old_score) ? score : old_score;
}

만일 scoreold_scoredouble 이나 float 이었을 경우,
다음과 같이 별도로 함수를 정의해야합니다.
public static Int32 GetHighestScore()
{
    return (score > old_score) ? score : old_score;
}

double score = 5;
double old_score = 3;

public static double GetHighestScoreA()
{
    return (score > old_score) ? score : old_score;
}

이와 같이, 복수의 패턴을 상정한 함수를 정의하는 것으로 해결합니다.
그러나 이것은 나쁜 예입니다.
하드 코딩이며 프로그램의 유지 보수성 (보수성)도 최악입니다.
이것을 해결해주는 것이 제네릭입니다.

이 경우 다음과 같이 함수 정의를 수행합니다.
static Int32 score = 5;
static Int32 old_score = 3;

public static unsafe T GetHighestScore<T>(T one, T two) where T : unmanaged, IComparable
{
    if(one.CompareTo(two) > 0)
    {
        return one;
    }
    return two;
}

여기서, where T : unmanaged 는, 형태가 언매니지드형인 것을 조건으로 한다고 하는 의미입니다.

관리되지 않는 유형이란?


sbyte byte , short , int , uint , long ,ulong , char , float , double , decimal , bool가 관리되지 않는 유형입니다.
비관리형(C# 참조)

실례



실례로서, MarshalStructureToPtr 를 메소드로서 간이화해 보겠습니다.
(※ Marshal.StructureToPtr() 도 제네릭형으로서 정의되고 있군요!)
public struct myStruct
{
    public int x;
    public int y;
}

static void Main(string[] args)
{
    Console.Title = "ジェネリック";

    myStruct ms = new myStruct();
    var pStructure = StructureToPointer<myStruct>(ms);
    Console.WriteLine("構造体ポインタ: " + (Int32)(pStructure));

    Console.ReadKey();
}

////////////////////////////////////////////////////////////////////////
// 構造体のマーシャリング
////////////////////////////////////////////////////////////////////////
public unsafe static IntPtr StructureToPointer<T>(T 構造体) where T : struct
{
    var size = Marshal.SizeOf(構造体.GetType());
    IntPtr pStructure = Marshal.AllocCoTaskMem(size); //アンマネージドメモリの確保
    Marshal.StructureToPtr(構造体, pStructure, false); //確保した領域に構造体ポインタを展開
    Marshal.DestroyStructure(pStructure, typeof(T));//後処理
    Marshal.FreeCoTaskMem(pStructure);//確保したアンマネージドメモリの解放
    return pStructure;
}

구조체에서 구조체 포인터로의 마샬링을 단순화하는 함수입니다.
여기서는, where T : struct 라고 해, 형태가 struct 인 것을 조건으로 합니다.

본래, 매니지드형인 (언매니지드형이 아니다) 제네릭 함수에서는 sizeof() (을)를 사용할 수 없습니다. ( sizeof() 가 언매니지드형에만 대응하고 있기 때문에)
그래서 Marshal.Sizeof() 를 사용합니다.

실행 결과:

좋은 웹페이지 즐겨찾기