값형과 참조형의 차이점
메모리 할당 방식, 스택/힙 저장 위치, 복사 전략 측면에서 비교한다. 주요 값형과 참조형 타입을 나열한다.
1. 메모리 구조와 저장 방식
- 값형 (Value Type):
- 데이터 자체를 직접 저장한다.
- 일반적으로 스택에 할당되며, 클래스 멤버로 사용될 경우 해당 객체의 힙 영역에 포함된다.
- 변수 대입 시 데이터 전체를 복사(깊은 복사)한다.
- 참조형 (Reference Type):
- 실제 데이터의 메모리 주소를 저장한다.
- 인스턴스는 힙에 생성되며, 변수는 이 주소를 참조한다(스택에 주소 저장).
- 대입 시 주소만 복사(얕은 복사)되므로 동일한 객체를 공유한다.
2. 대표적인 타입 예시
- 값형:
int,double,bool,DateTime(struct),enum - 참조형:
class(예:string,object), 배열(int[]),interface,Delegate
3. 코드 예시 비교
int first = 42; // 값형 - 스택에 42 저장
int second = first; // 복사 후 독립된 값 유지
object instance = new object(); // 참조형 - 힙에 인스턴스 생성
object copyRef = instance; // 주소 복사 - 두 변수가 동일한 객체 참조
비동기 처리 기법
async/await의 목적과, 비동기 작업에서 발생할 수 있는 데드락 문제 해결 방법을 설명하며, Task.Run과 Task.Factory.StartNew의 활용 차이를 분석한다.
1. async/await의 역할
- 비동기 로직을 동기식 코드처럼 작성 가능하게 해주는 패러다임.
- 콜백 지옥 회피: 중첩된 콜백 없이 순차적 흐름 유지.
- 비차단성:
await시 현재 스레드를 해제하고 다른 작업 수행 가능, 완료 후 복귀. - 컴파일러가 상태 머신으로 변환하여 일시정지 및 재개를 관리.
2. 데드락 방지 전략
- 비동기 작업을 차단하지 않기:
- 오류:
.Result또는.Wait()를 동기 코드에서 사용하면 스레드 블록 발생. - 해결: 항상
await사용, 차단 연산 금지.
- 오류:
- 동기 컨텍스트 무시하기:
- 라이브러리 내부에서는
ConfigureAwait(false)를 사용하여 원래 컨텍스트(예: UI 스레드)를 고려하지 않도록 한다. - 예시:
var data = await FetchData().ConfigureAwait(false);
- 라이브러리 내부에서는
- Task.Run vs Task.Factory.StartNew:
Task.Run:- 스레드 풀을 자동으로 사용.
- 간단한 CPU 집약 작업에 적합.
- 예:
await Task.Run(() => HeavyCalculation(1000));
Task.Factory.StartNew:- 더 많은 제어 옵션 제공 (예:
TaskCreationOptions.LongRunning). - 장시간 실행되는 작업이나 특수한 스케줄링이 필요한 경우 사용.
- 예:
var task = Task.Factory.StartNew(() => LongRunningProcess(), TaskCreationOptions.LongRunning);
- 더 많은 제어 옵션 제공 (예:
델리게이트와 이벤트
델리게이트의 본질과 이벤트의 역할, 그리고 사용자 정의 이벤트의 구현 방법을 설명한다.
1. 델리게이트의 본질
- 타입 안전한 함수 포인터로서,
System.Delegate의 파생 클래스이다. - 메서드 서명을 정의하여 특정 형식의 메서드만 참조할 수 있도록 보장.
- 다중 호출 지원: 하나의 델리게이트 인스턴스에 여러 메서드를 등록 가능 (
+=사용).
2. 이벤트와 델리게이트의 관계
- 이벤트는 델리게이트의 래핑:
- 이벤트는 특정 델리게이트 타입을 기반으로 하지만, 외부에서만 구독/취소 가능.
- 내부에서만
Invoke가능하므로 안전한 관찰자 패턴을 제공.
- 예시 코드:
public delegate void ClickHandler(object sender, EventArgs e); public class Button { public event ClickHandler? Clicked; public void TriggerClick() { Clicked?.Invoke(this, EventArgs.Empty); } }
3. 사용자 정의 이벤트 실습
public class EnvironmentalMonitor
{
public delegate void TemperatureUpdateHandler(double temperature);
public event TemperatureUpdateHandler? TemperatureUpdated;
private double currentReading;
public double CurrentTemperature
{
get => currentReading;
set
{
currentReading = value;
TemperatureUpdated?.Invoke(value);
}
}
}
비동기 프로그래밍 확장: 특성 사용
ASP.NET MVC의 [HttpGet], [Route] 등의 특성 기능을 설명하고, 사용자 정의 특성을 만드는 절차를 소개한다.
1. ASP.NET MVC 특성의 역할
[HttpGet]: 해당 액션 메서드가 오직 HTTP GET 요청만 처리하도록 제한.- 예시:
[HttpGet] public ActionResult GetUser(int id) { return View(); } [Route]: URL 경로 템플릿을 정의하여 요청을 액션에 매핑.- 예시:
[Route("api/products/{id}")] public ActionResult GetProductById(int id) { return Json(new { Id = id }); }
2. 사용자 정의 특성 만들기
- Attribute 상속:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class AuditLogAttribute : Attribute { public string Message { get; } public AuditLogAttribute(string message) { Message = message; } } - 특성 적용:
[AuditLog("사용자 정보 조회")] public ActionResult GetUserData(int userId) { return Json(...); } - 반사로 특성 읽기:
var method = typeof(HomeController).GetMethod("GetUserData"); var auditAttr = method.GetCustomAttribute<AuditLogAttribute>(); Console.WriteLine(auditAttr?.Message); // 출력: "사용자 정보 조회"