using System;
using System.Collections.Generic;
public class Box<T>
{
public T Value { get; set; }
public void DisplayValue()
{
Console.WriteLine($"Value: {Value}");
}
}
class Program
{
static void Main(string[] args)
{
Box<int> intBox = new Box<int> { Value = 123 };
Box<string> strBox = new Box<string> { Value = "Hello, World" };
Box<DateTime> dateBox = new Box<DateTime> { Value = DateTime.Now };
intBox.DisplayValue();
strBox.DisplayValue();
dateBox.DisplayValue();
}
}
1. 다음 코드에서 제네릭을 사용한 부분을 식별하고, 해당 코드가 제네릭을 사용하지 않았을 때 발생할 수 있는 문제점에 대해 설명하세요.
2. 아래 코드가 어떤 기능을 하는지, 어떤 방식으로 동작하는지 간단하게 설명해주세요.
public static T Max<T>(T a, T b) where T : IComparable<T> { return a.CompareTo(b) > 0 ? a : b; }
제네릭을 사용한 부분:
public class Box: 클래스 정의에서 제네릭 타입 T를 사용합니다.
public T Value { get; set; }: 클래스 속성에 제네릭 타입 T를 사용합니다.
Box intBox, Box strBox, Box dateBox: 각기 다른 타입으로 제네릭 클래스를 인스턴스화합니다.
제네릭을 사용하지 않았을 때 발생할 수 있는 문제점:
타입 안정성: 제네릭을 사용하면 컴파일 타임에 타입 검사가 이루어지기 때문에, 잘못된 타입의 값이 들어가는 것을 방지할 수 있습니다. 제네릭을 사용하지 않으면 박싱(Boxing)과 언박싱(Unboxing)을 통해 오브젝트 타입으로 변환해야 하며, 잘못된 타입의 값이 들어가도 런타임까지 에러가 발생하지 않습니다.
코드 중복: 제네릭을 사용하지 않으면 각 타입에 대해 별도의 클래스를 작성해야 하기 때문에 코드 중복이 발생할 수 있습니다. 예를 들어, Box, Box, Box 등을 각각 별도로 작성해야 합니다.
성능: 박싱과 언박싱은 성능에 영향을 미칠 수 있습니다. 제네릭을 사용하면 이러한 불필요한 변환 과정을 줄일 수 있습니다.
동작 방식:
제네릭 메서드 정의: Max 메서드는 제네릭 타입 T를 사용합니다. 이 메서드는 어떤 타입이든 받아들일 수 있지만, 타입 T는 반드시 IComparable 인터페이스를 구현해야 합니다.
매개변수 비교: a.CompareTo(b)를 호출하여 a와 b를 비교합니다. CompareTo 메서드는 a가 b보다 크면 양수를, 같으면 0을, 작으면 음수를 반환합니다.
더 큰 값 반환: a.CompareTo(b) > 0 조건이 참이면 a를 반환하고, 그렇지 않으면 b를 반환합니다.
int result = Max(5, 10); // result는 10이 됩니다.
string strResult = Max("apple", "orange"); // strResult는 "orange"가 됩니다.
위 예제에서 Max 메서드는 int와 string 타입에 대해 올바르게 동작하며, 각각 최대 값을 반환합니다.
제네릭(Generic)이란:
제네릭은 클래스, 인터페이스, 메서드 등을 정의할 때 데이터 타입을 하나 이상 지정하지 않고, 나중에 사용할 때 구체적인 타입을 명시할 수 있도록 하는 기능입니다
람다식(Lambda Expression)이란:
람다식은 익명 메서드(Anonymous Method)를 단순화한 형태로, 메서드를 하나의 식(expression)으로 표현한 것입니다. 주로 함수형 프로그래밍을 지원하고, 간결한 코드를 작성하는 데 유용합니다.
LINQ(Language Integrated Query)란:
LINQ는 .NET 언어에 쿼리 기능을 통합한 것으로, 컬렉션 데이터를 조작하고 쿼리하는 통합된 방법을 제공합니다. SQL과 유사한 문법을 사용하여 컬렉션, XML, 데이터베이스 등 다양한 데이터 소스에 대해 쿼리를 수행할 수 있습니다.
리플렉션이란 무엇인가요?
리플렉션(Reflection)이란:
리플렉션은 런타임에 어셈블리의 메타데이터를 읽고, 객체의 정보를 동적으로 조작할 수 있는 기능입니다. 이를 통해 타입, 메서드, 속성, 필드 등을 런타임에 동적으로 조사하고 인스턴스화할 수 있습니다.
사용 예시:
타입 정보 조회: 런타임에 객체의 타입 정보를 얻을 수 있습니다.
동적 메서드 호출: 런타임에 메서드를 동적으로 호출할 수 있습니다.
동적 인스턴스 생성: 런타임에 객체를 동적으로 생성할 수 있습니다.
플러그인 시스템: 런타임에 외부 어셈블리를 로드하고 플러그인을 동적으로 실행할 때.
ORM(Object-Relational Mapping): 데이터베이스 테이블과 클래스 간의 매핑을 동적으로 처리할 때.
테스트 프레임워크: 테스트 메서드를 동적으로 탐색하고 실행할 때.
리플렉션의 단점:
성능 저하: 런타임에 메타데이터를 읽고 조작하는 과정이 느리기 때문에 성능에 영향을 미칠 수 있습니다.
안전성: 컴파일 타임이 아닌 런타임에 오류가 발생할 수 있어, 타입 안전성이 떨어집니다.
복잡성: 리플렉션을 사용하는 코드는 이해하기 어렵고, 유지 보수가 복잡할 수 있습니다.