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();
}
}
public class Box<T>
로 제네릭을 선언했습니다.
제네릭 <T>
를 사용하지 않았다면 구동 코드에서 Box클래스가 다양한 자료형을 받아서 동작하지 못하고 버그가 생겼을 것 입니다.
Box에 들어가는 Value 값을 제네릭으로 사용하였다.
제네릭을 사용하지 않게 되면 각 변수 타입에 대응되는 필드를 선언하고,
생성자에서 파라미터를 각각 다르게 받아 각 필드를 초기화 해줘야 하는 문제점이 발생한다.
추가로, 사용되지 않는 필드를 선언해 둘 확률이 크다.
public static T Max<T>(T a, T b) where T : IComparable<T> { return a.CompareTo(b) > 0 ? a : b; }
a와 b를 매개 변수로 받아 a와 b중 큰 것을 반환하는 제네릭 메서드를 정의합니다.
이 메서드는 T타입이 IComparable 인터페이스를 구현해야 한다는 제약조건(where T : IComparable<T>
)를 가지고 있습니다.
a와 b를 비교해서 a가 더 크면 a를, b가 더 크면 b를 반환해준다.
제네릭으로 선언된 a와 b를 비교하되, IComparable에서 파생된 클래스인 경우에만 사용할 수 있도록 where절로 제약을 걸어두었다.
제네릭은 데이터 타입을 일반화하여 코드의 재사용성, 타입 안정성, 성능을 향상시키는 프로그래밍 기법입니다. 제네릭을 사용하면 다양한 데이터 타입에 대해 동일한 코드를 사용할 수 있으며, 컴파일 시점에 타입 체크를 수행하여 타입 안정성을 보장받을 수 있습니다. 이는 코드의 중복을 줄이고, 타입 캐스팅에 따른 런타임 오류의 가능성을 낮추며, 성능을 최적화하는 데 도움이 됩니다.
제네릭에 대해 알고 있는대로 적절하게 설명해주면 좋습니다.
데이터 형식을 일반화하여 코드의 재사용성과 유연성을 향상시켜 주는 기능이다.
다양한 형식에 대응되는 메서드와 클래스 작성에 용이하며 컴파일 시 안정성을 보장해준다.
람다식은 간결한 방식으로 익명 함수(이름이 없는 함수)를 정의할 수 있는 표현식입니다. 람다식을 사용하면 코드를 더 간결하고 읽기 쉽게 만들 수 있으며, 이벤트 핸들러, LINQ 쿼리, 콜백 함수 등을 작성할 때 유용합니다.
람다식은 일반적으로 다음과 같은 구조를 가집니다.
(매개변수 목록) => 표현식 또는 문장 블록
무명 메서드를 같이 언급해주면 좋습니다.
무명 메서드를 만들기 위해서 사용하며 간결하고 가독성이 높은 코드 작성에 활용할 수 있다.
(매개변수목록) => 식 의 형태로 사용한다.
LINQ(Language Integrated Query)는 데이터를 쿼리하는 강력한 방법을 제공합니다. 이는 C# 언어에 직접 통합되어 있어, 컬렉션, 데이터베이스, XML 문서 및 기타 데이터 소스에 대한 쿼리를 쉽고 일관된 방식으로 작성할 수 있게 해줍니다. LINQ를 사용하면 복잡한 데이터 처리와 변환 작업을 간결하고 읽기 쉬운 코드로 표현할 수 있습니다.
Query를 같이 언급해주면 좋습니다. C# 개체에 쿼리를 할 수 있도록 사용하는 모델이라고 대답해주면 됩니다.
Language Integrated Query 라고해서 특정 데이터들에서 Query를 하여 데이터를 빠르고 편리하게 추출하는 방식이라 할 수 있습니다. 컬렉션 형태를 띄는 모든 데이터에 질의를 할 수 있으며, 이 강력한 기능을 통해 복잡한 구문을 좀 더 간단하게 필터링하거나 정렬할 수 있다는 등의 특징을 지니고 있습니다. 가독성 면에서 뛰어나지만, 유니티에서 활용할 때에는 오히려 처리 속도가 저하된다. (.Net7 버전부터는 빠르지만 유니티에서 지원하지 않음)
리플렉션은 프로그램이 실행 중에 자신의 구조를 검사하고, 수정할 수 있는 기능을 말합니다. C#과 같은 .NET 언어에서 리플렉션은 System.Reflection 네임스페이스를 통해 제공됩니다. 리플렉션을 사용하면 실행 시간에 객체의 타입을 확인하고, 타입의 멤버(메서드, 프로퍼티, 필드 등)에 접근하거나, 인스턴스를 생성하고, 메서드를 실행하고, 어트리뷰트를 읽는 등 다양한 작업을 수행할 수 있습니다.
사용해 본 적 없습니다.
성능 저하: 리플렉션은 실행 시간에 타입 정보를 조회하고, 메서드를 동적으로 호출하는 등의 작업을 수행하기 때문에, 직접적인 코드 호출에 비해 성능이 저하될 수 있습니다. 특히, 반복적으로 리플렉션을 사용하는 경우 성능 저하가 두드러질 수 있습니다.
타입 안정성 감소: 리플렉션을 사용하면 컴파일 시점에 타입 체크를 할 수 없기 때문에, 실행 시점에 타입 관련 오류가 발생할 가능성이 높아집니다. 이는 디버깅을 어렵게 만들 수 있습니다.
보안 문제: 리플렉션을 사용하면 애플리케이션의 내부 구조를 외부에서 쉽게 접근할 수 있게 되므로, 보안에 취약해질 수 있습니다. 특히, private 멤버에 접근할 수 있게 되므로, 캡슐화 원칙이 약화될 수 있습니다.
- 리플렉션 질문은 여러분들에게 함정이 될 가능성이 정말 높은 질문입니다.
- 캡슐화를 깨는 방식이기 때문에 확실한 목적성 없이 사용했을 경우 정말 큰 감점이 될 수 있습니다.
- 따라서 리플렉션 질문을 받았을 경우, 최대한 사용 시 주의점과 단점을 위주로 설명해주시고,
프로젝트에 리플렉션을 사용했다면 사용 이유를 분명하게 밝혀야 하고,
아니라면 앞서 언급한 주의점과 단점을 근거로 사용하지 않았다고 설명해주면 됩니다.
클래스 타입, 메서드, 프로퍼티 등의 메타 정보를 런타임 중에 알아내는 기능.
다른 모듈에 선언된 인스턴스를 생성하거나, 기존 개체에서 형식을 가져오고 해당하는 메소드를 호출, 또는 해당 필드와 속성에 접근할 수 있는 기능을 제공한다.
유니티 Event 처리 방식 중 Send Message, Broadcast Message 등이 이를 활용한 기능이며,이벤트 발생 시의 처리를 위해서 사용하였다.
그러나, Reflection은 객체 지향에서 중요하게 생각하는 캡슐화를 망가뜨리는 방식이다.
(private으로 선언된 멤버에도 접근할 수 있다.)
추가로 문자열 검색을 모든 내용에 대해 수행하므로 속도가 느리며 성능 저하를 유발한다.
리플렉션을 사용하여 string을 사용하지 않고 클래스의 이름을 출력해보는 함수를 만들어봅시다.
using System;
using System.Reflection;
public class Character
{
public int Level { get; set; }
public void PrintClassName()
{
// TODO: 리플렉션을 사용하여 클래스의 이름을 출력하는 코드 작성
Console.WriteLine(this.GetType().Name);
//
}
}
public class Warrior : Character
{
}
public class Mage : Character
{
}
public class Archer : Character
{
}
class Program
{
static void Main(string[] args)
{
Warrior warrior = new Warrior();
Mage mage = new Mage();
Archer archer = new Archer();
// 리플렉션을 사용하여 클래스 이름 출력
warrior.PrintClassName();
mage.PrintClassName();
archer.PrintClassName();
}
}
using System;
using System.Reflection;
public class Character
{
public int Level { get; set; }
public void PrintClassName()
{
// TODO: 리플렉션을 사용하여 클래스의 이름을 출력하는 코드 작성
Console.WriteLine($"Class Name: {GetType().Name}");
//
}
}
public class Warrior : Character
{
}
public class Mage : Character
{
}
public class Archer : Character
{
}
class Program
{
static void Main(string[] args)
{
Warrior warrior = new Warrior();
Mage mage = new Mage();
Archer archer = new Archer();
// 리플렉션을 사용하여 클래스 이름 출력
warrior.PrintClassName();
mage.PrintClassName();
archer.PrintClassName();
}
}