πŸ’» Programming Language/C#

26. μ œλ„€λ¦­μŠ€(Generics) νƒ€μž… μ œμ•½

S.Honey 2022. 4. 7. 09:38
  • μ œλ„€λ¦­μŠ€ νƒ€μž… μ œμ•½

  • μ•žμ—μ„œ λ‚˜μ˜¨ μΌλ°˜ν™” λ©”μ†Œλ“œ, μΌλ°˜ν™” ν΄λž˜μŠ€μ—μ„œ μ‚¬μš©ν•˜λ˜ T(Type Parameter)λŠ” λͺ¨λ“  데이터 ν˜•μ‹μ„ λŒ€μ‹ ν•  수 μžˆλŠ” λ§€κ°œλ³€μˆ˜λ‘œ μ‚¬μš©λ˜μ—ˆλ‹€.

  • λͺ¨λ“  ν˜•μ‹μ„ λŒ€μ‹ ν•˜λŠ” λ§€κ°œλ³€μˆ˜κ°€ ν•„μš”ν•  μˆ˜λ„ μžˆμ§€λ§Œ κ·Έλ ‡μ§€ μ•Šμ€ κ²½μš°λ„ μ‘΄μž¬ν•  수 μžˆλ‹€.

    • 그런 κ²½μš°μ—λŠ” λ§€κ°œλ³€μˆ˜μ— μ œμ•½ 쑰건을 쀄 수 μžˆλ‹€.
  • μ œμ•½ 쑰건 μ£ΌλŠ” λ°©λ²•μœΌλ‘œ whereμ ˆμ„ μ΄μš©ν•œλ‹€.


Ex) 

class DemoList<T> where T : DemoClass 
{
    ...
}
  • μœ„μ™€ 같은 κ²½μš°μ— TλΌλŠ” λ§€κ°œλ³€μˆ˜λŠ” "DemoClass둜 λΆ€ν„° μƒμ†λ°›λŠ” ν˜•μ‹μ΄μ–΄μ•Ό ν•œλ‹€" λΌλŠ” 의미
void CopyData<T>(T a, T b) where T : struct 
// structλŠ” 기본적으둜 value type(κ°’ ν˜•μ‹)
{
...
}
  • μœ„μ™€ 같은 경우 TλŠ” "κ°’ ν˜•μ‹μ΄μ–΄μ•Ό ν•œλ‹€"λΌλŠ” μ œμ•½μ‘°κ±΄μ„ μ€€ μ˜λ―Έμ΄λ‹€.

μ œλ„€λ¦­μŠ€μ—μ„œ μ œμ•½μ‘°κ±΄μ„ μ£ΌλŠ” 방식은

    where T: μ œμ•½μ‘°κ±΄

μ œμ•½μ‘°κ±΄μ˜ μ’…λ₯˜

문법 의미
where T : struct Tκ°€ κ°’ν˜•μ‹μ΄μ–΄μ•Ό ν•œλ‹€.
where T : class TλŠ” μ°Έμ‘°ν˜•μ‹μ΄μ–΄μ•Ό ν•œλ‹€.
where T : new() TλŠ” λ°˜λ“œμ‹œ κΈ°λ³Έ μƒμ„±μžκ°€ μžˆμ–΄μ•Ό ν•œλ‹€.(λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” μƒμ„±μžμ—¬μ•Ό ν•œλ‹€.) => κΈ°λ³Έμƒμ„±μžκ°€ μ—†μœΌλ©΄ μ•ˆλœλ‹€.
where T : 기반클래슀λͺ… TλŠ” 기반 클래슀의 νŒŒμƒ ν΄λž˜μŠ€μ—¬μ•Ό ν•œλ‹€.
where T : μΈν„°νŽ˜μ΄μŠ€λͺ… TλŠ” ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ°˜λ“œμ‹œ κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.(μΈν„°νŽ˜μ΄μŠ€ λͺ…은 μ—¬λŸ¬κ°œκ°€ 올 수 μžˆλ‹€.)
where T : U TλŠ” 또 λ‹€λ₯Έ ν˜•μ‹ λ§€κ°œλ³€μˆ˜ Uλ‘œλΆ€ν„° 상속받은 ν΄λž˜μŠ€μ—¬μ•Ό ν•œλ‹€.

Generic μ œμ•½μ‘°κ±΄ ν™œμš© 예제 μ½”λ“œ


namespace GenericsConstraintEx
{
    class DemoArray1<T> where T : struct
    {
        public T[] Array { get; set; }
        public DemoArray1(int size)
        {
            Array = new T[size];
        }

        public int Length
        {
            get { return Array.Length; }
        }
    }

    class DemoArray2<T> where T : class
    {
        public T[] Array { get; set; }
        public DemoArray2(int size)
        {
            Array = new T[size];
        }
    }

    class Parent { }
    class Child : Parent { }

    class DemoArray3<U> where U : Parent
    {
        public U[] Array { get; set; }
        public DemoArray3(int size)
        {
            Array = new U[size];
        }

        public void CopyData<T>(T[] a) where T : U
        {
            a.CopyTo(Array, 0);
            //Array둜 0번 μΈλ±μŠ€λΆ€ν„° λ³΅μ‚¬ν•œλ‹€λŠ” 의미
        }
    }

    class Program
    {
        public static T CreateInstance<T>() where T : new()
        {
            return new T();
        }

        static void Main(string[] args)
        {
            DemoArray1<int> aa = new DemoArray1<int>(2);
            aa.Array[0] = 11;
            aa.Array[1] = 22;

            for (int i = 0; i < aa.Length; i++)
            {
                Console.WriteLine(aa.Array[i]);
            }

            //DemoArray2<int> bb = new DemoArray2<int>(2); 
            // => μ΄λ ‡κ²Œ μ‚¬μš©ν•˜λ©΄ DemoArray2λŠ” class ν˜• μ œμ•½μ‘°κ±΄μœΌλ‘œ 인해 였λ₯˜κ°€ λ°œμƒν•œλ‹€.
            DemoArray2<DemoArray1<double>> bb = new DemoArray2<DemoArray1<double>>(2);
            bb.Array[0] = new DemoArray1<double>(3);
            bb.Array[1] = new DemoArray1<double>(10);

            DemoArray3<Parent> cc = new DemoArray3<Parent>(3);
            cc.Array[0] = new Parent();
            cc.Array[1] = new Child();
            //child도 parentλ₯Ό μƒμ†ν•˜κΈ°μ— κ°€λŠ₯ν•˜λ‹€.
            cc.Array[2] = CreateInstance<Parent>();

            DemoArray3<Child> dd = new DemoArray3<Child>(2);
            //dd.Array[0] = Parent(); 
            // => Uνƒ€μž…μ΄ Child둜 μ„ μ–Έλ˜μ—ˆκΈ° λ•Œλ¬Έμ— λΆ€λͺ¨ν΄λž˜μŠ€μΈ ParentλŠ” λ“€μ–΄κ°ˆ 수 μ—†λ‹€.
            dd.Array[0] = new Child();
            dd.Array[1] = CreateInstance<Child>();

            DemoArray3<Child> ee = new DemoArray3<Child>(2);
            ee.CopyData<Child>(dd.Array);
            //주의 : 단 λ°°μ—΄μ˜ κΈΈμ΄λŠ” 같아야함.
        }
    }
}
Output

11
22