c# 예외 처리(try-catch)

2024. 9. 22. 16:41카테고리 없음

개요

예외 처리, 값형과 참조형에 대해 알아보겠습니다

내용 - 예외란?

  • 예외는 프로그램 실행 중에 발생하는 예기치 않은 상황을 의미합니다.
  • 예외는 프로그램의 정상적인 흐름을 방해하고 오류를 야기할 수 있습니다.

내용 - 예외 처리 구현

  • C#에서는 try-catch 블록을 사용하여 예외 처리를 수행합니다.
  • try 블록 내에서 예외가 발생할 수 있는 코드를 작성하고, catch 블록에서 예외를 처리합니다.

예외 처리 구현 코드

try
{
    // 예외가 발생할 수 있는 코드
}
catch (ExceptionType1 ex)
{
    // ExceptionType1에 해당하는 예외 처리
}
catch (ExceptionType2 ex)
{
    // ExceptionType2에 해당하는 예외 처리
}
finally
{
    // 예외 발생 여부와 상관없이 항상 실행되는 코드
}

 

내용 - finally 블록

  • finally 블록은 예외 발생 여부와 상관없이 항상 실행되는 코드 블록입니다.
  • finally 블록은 예외 처리의 마지막 단계로, 예외 발생 시 정리 작업이나 리소스 해제 등의 코드를 포함할 수 있습니다.
  • finally 블록은 try-catch 블록 뒤에 작성되며, 생략할 수도 있습니다.

내용 - 사용자 정의 예외 처리

public class NegativeNumberException : Exception
{
    public NegativeNumberException(string message) : base(message)
    {
    }
}
static void Main(string[] args)
{
    try
    {
        int number = 110;
        if (number < 0)
        {
            throw new NegativeNumberException("음수는 처리할 수 없습니다."); //일부러 코드 에러를 발생시킬때 throw를 사용한다.
        }
    }
    catch (NegativeNumberException ex)
    {
        Console.WriteLine(ex.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("예외가 발생했습니다: " + ex.Message);
    }
}

코드설명

public NegativeNumberException(string message) : base(message) :

- base(message) 이부분이 이니셜라이저 이고, 이니셜라이저는 생성자가 실행 되기전에 처리할 것들을 명시해준다.
- base는 부모를 말한다.(Exception의 생성자를 먼저 처리하고 온다.)

- 진행 순서는 NegativeNumberException 이 실행이 되면 부모에 생성자를 먼저 메세지를 전달해서 동작을 하고  NegativeNumberException생성자가 동작을 한다.

 

내용 - 값형과 참조형

값형(Value Type)

  • 값형은 변수에 값을 직접 저장합니다.
  • 변수가 실제 데이터를 보유하고 있으며, 해당 변수를 다른 변수에 할당하거나 전달할 때는 값이 복사됩니다.
  • 값형 변수의 수정은 해당 변수의 값만 변경하므로 다른 변수에 영향을 주지 않습니다.
  • int, float, double, bool 등의 기본 데이터 타입들이 값형에 해당합니다.

참조형(Reference Type)

  • 참조형은 변수가 데이터에 대한 참조(메모리 주소)를 저장합니다.
  • 변수가 실제 데이터를 가리키는 참조를 갖고 있으며, 해당 변수를 다른 변수에 할당하거나 전달할 때는 참조가 복사됩니다.
  • 참조형 변수의 수정은 동일한 데이터를 가리키고 있는 다른 변수에 영향을 줄 수 있습니다.
  • 클래스, 배열, 인터페이스 등이 참조형에 해당합니다.

값형과 참조형의 차이점

  • 값형은 실제 데이터를 변수에 저장하고, 참조형은 데이터에 대한 참조를 변수에 저장합니다.
  • 값형은 변수 간의 값 복사가 이루어지고, 참조형은 변수 간의 참조 복사가 이루어집니다.
  • 값형은 변수가 독립적으로 데이터를 가지며, 참조형은 변수가 동일한 데이터를 참조합니다.

내용 - 박싱과 언박싱

값형과 참조형 사이의 변환을 의미

박싱(Boxing)

  • 박싱은 값형을 참조형으로 변환하는 과정을 말합니다.
  • 값형 변수의 값을 메모리의 힙 영역에 할당된 객체로 래핑합니다.
  • 박싱을 통해 값형이 참조형의 특징을 갖게 되며, 참조형 변수로 다뤄질 수 있습니다.
  • 박싱된 값형은 참조로 전달되므로 메모리 오버헤드가 발생할 수 있습니다.

언박싱(Unboxing)

  • 언박싱은 박싱된 객체를 다시 값형으로 변환하는 과정을 말합니다.
  • 박싱된 객체에서 값을 추출하여 값형 변수에 할당합니다.
  • 언박싱은 명시적으로 타입 캐스팅을 해야 하며, 런타임에서 타입 검사가 이루어집니다.
  • 잘못된 형식으로 언박싱하면 런타임 에러가 발생할 수 있습니다.

박싱과 언박싱의 주요 특징

  • 박싱과 언박싱은 값형과 참조형 사이의 변환 작업이므로 성능에 영향을 미칠 수 있습니다. 반복적인 박싱과 언박싱은 성능 저하를 초래할 수 있으므로 주의해야 합니다.
  • 박싱된 객체는 힙 영역에 할당되므로 가비지 컬렉션의 대상이 될 수 있습니다. 따라서 메모리 관리에 유의해야 합니다.
  • 박싱된 객체와 원래의 값형은 서로 독립적이므로 값을 수정하더라도 상호간에 영향을 주지 않습니다.

참고사항( object )

object는 .NET Common Type System (CTS)의 일부이며, 모든 클래스의 직간접적인 상위 클래스입니다. 모든 클래스는 object에서 상속되며, object는 모든 형식을 참조할 수 있는 포괄적인 타입입니다.

박싱과 언박싱 예시 코드

using System;

class Program
{
    static void Main()
    {
        // 값형
        int x = 10;
        int y = x;
        y = 20;
        Console.WriteLine("x: " + x); // 출력 결과: 10
        Console.WriteLine("y: " + y); // 출력 결과: 20

        // 참조형
        int[] arr1 = new int[] { 1, 2, 3 };
        int[] arr2 = arr1;
        arr2[0] = 4;
        Console.WriteLine("arr1[0]: " + arr1[0]); // 출력 결과: 4
        Console.WriteLine("arr2[0]: " + arr2[0]); // 출력 결과: 4

        // 박싱과 언박싱
        int num1 = 10;
        object obj = num1; // 박싱
        int num2 = (int)obj; // 언박싱
        Console.WriteLine("num1: " + num1); // 출력 결과: 10
        Console.WriteLine("num2: " + num2); // 출력 결과: 10
    }
}

 

리스트 활용 예제

List<object> myList = new List<object>();

// 박싱: 값 형식을 참조 형식으로 변환하여 리스트에 추가
int intValue = 10;
myList.Add(intValue); // int를 object로 박싱하여 추가

float floatValue = 3.14f;
myList.Add(floatValue); // float를 object로 박싱하여 추가

// 언박싱: 참조 형식을 값 형식으로 변환하여 사용
int value1 = (int)myList[0]; // object를 int로 언박싱
float value2 = (float)myList[1]; // object를 float로 언박싱