C#/C# 기본

[C#] Generic 프로그래밍 / 예외 처리

로파이 2021. 10. 12. 21:55

C#의 일반화 프로그래밍 Generic Programming

C++에서 template<typename T>를 C#에서 어떻게 하는 지 알아본다.

 

일반화 메서드

메서드 이름 뒤에 <T>를 붙여 임의의 타입에 대해 동작하는 일반화 메서드를 정의한다.

 

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

 

일반화 클래스

클래스도 마찬가지로 클래스 이름 뒤에 <T>를 붙인다.

  class Container<ElementType>
    {
        private ElementType[] array;
        public Container()
        {
        }
        public ElementType this[int index]
        { 
            get { return array[index]; } 
            set { array[index] = value; } 
        }
        public int Length { get { return array.Length; } }
    }

 

C#에서는 where 절을 이용하여 해당 클래스의 타입 T에 대해 제약을 추가할 수 있다.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters

제약조건 설명
where T : struct value type 이면서 non-nullable 인자를 사용 가능하다. struct 타입은 new()가 가능하기 때문에 new 제약사항과 혼용할 수 없다. 또한 unmanaged 제약사항을 쓸 수 없다.
where T : class reference type이면서 non-nullable 인자를 사용가능하다. 이 제약사항은 클래스, 인터페이스, 델리게이트, 혹은 배열타임이 가능하다.
where T : class? reference type과 nullable 인자를 사용가능하다.
where T : notnull non-nullable 인자만 사용가능하다.
where T : default C# 9.0이상에서 이 제약사항은 기반 메서드를 오버라이드할 때 제약사항이 없는 메서드를 오버라이드하겠다는 의미를 지닌다.
where T : unmanaged non-nullable unmanaged type 인자로 제약한다. 이 제약은 struct를 암시하기 때문에 struct와 new()를 같이 사용할 수 없다.
where T : new() 매개변수가 없는 public new()를 호출할 수 있어야한다. struct와 unmanaged와 같이 사용할 수 없다.
where T : base_class_name T가 기반 클래스가 base_class_name 이어야한다.
where T : interface_name T가 interface_name을 상속한 클래스이어야한다.
where T : U T는 또다른 인자 U 클래스로 부터 상속한 클래스이어야한다.

 

간단한 예시

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

    }

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

    }

    class ObjectBase { }

    class Object : ObjectBase { }

    class BaseArray<U> where U : ObjectBase
    { 
        public U[] Array { get; set; }
        public BaseArray(int size) { Array = new U[size]; }
        public void CopyArray<T>(T[] Source) where T : U
        {
            Source.CopyTo(Array, 0);
        }
    }

 

예외처리하기

try-catch-finally 구문을 사용한다.

  • try 절 안에서 예외가 발생하면 catch 문 중 해당 예외에 대한 처리를 수행할 수 있다. 해당 예외가 없다면 프로그램은 멈춘다.
  • 모든 Exception은 System.Exception 클래스를 상속한다.
        static void Main(string[] args)
        {
            int[] arr = { 1, 2, 3 };

            try
            {
                for (int i = 0; i < 5; ++i)
                {
                    Console.WriteLine(arr[i]);
                }
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine($"예외가 발생했습니다. : { e.Message}");
            }

            try
            {
                throw new Exception("예외를 던진다.");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

C# 6.0에서 부터 when 절을 이용하여 예외를 선택적으로 처리할 수 있다.

        class FilterableException : Exception
        { public int ErroNo { get; set; } }

        static void Main(string[] args)
        {
            try
            {
                int num = Int32.Parse(input);

                if (num < 0 || num > 10)
                    throw new FilterableException() { ErroNo = num };
                else
                    Console.WriteLine($"Output : {num}");
            }
            catch (FilterableException e) when (e.ErroNo < 0)
            {
                Console.WriteLine("Negative Input is not allowed");
            }
            catch (FilterableException e) when (e.ErroNo > 10)
            {
                Console.WriteLine("Too big number is not allowed.");
            }
       }

사용자 예외 클래스를 만들고 예외가 발생할 때 해당 예외에 대한 속성을 지정한다. catch 문에서는 when 절을 통해 해당 속성 값에 따라 다른 예외처리를 수행한다.

 

finally

finally는 try 절이 실행되기만 한다면 반드시 실행됨을 보장하는 루틴이다. try 절 안에서 예외를 던진다면 catch 문에서 예외를 처리하고 finally가 실행된다. try 절 안에서 return을 하였거나 처리되지 않은 예외를 던진다하더라도 반드시 실행되는 구문이다.

            try
            {
                dbconn.Open(); // 데이터베이스 실행
            }
            catch(Exception e)
            {
                Console.WriteLine("예외 {0}", e.Message);
            }
            finally
            {
                dbconn.Close();
            }

'C# > C# 기본' 카테고리의 다른 글

[C#] 람다식  (0) 2021.10.15
[C#] 대리자와 이벤트  (0) 2021.10.15
[C#] 배열 / 컬렉션 / 인덱서  (0) 2021.10.11
[C#] 프로퍼티  (0) 2021.10.08
[C#] 인터페이스와 추상 클래스  (0) 2021.10.07