Deff_Dev

[C#] C# 심화 문법 (Generic, Linq, Reflection) 본문

면접 질문 정리/C#

[C#] C# 심화 문법 (Generic, Linq, Reflection)

Deff_a 2024. 7. 9. 10:32

제네릭이란 무엇인가요?

  • 제네릭(Generic)은 데이터 형식을 일반화하여 코드의 유연성을 높이는 기능
    • 일반화 ⇒ 특수한 개념으로부터 공통된 개념을 찾아 묶는 것 → 데이터 형식
  • 제네릭을 사용하면 데이터 형식에 의존하지 않는 클래스를 작성할 수 있어, 코드 재사용성과 타입 안정성을 높일 수 있다.
 

[Unity/C#] 일반화 프로그래밍 (Generic)

일반화란 ?- 특수한 개념으로부터 공통된 개념을 찾아 묶는 것 이러한 일반화를 이용하는 프로그래밍이 일반화 프로그래밍 ! 일반화 프로그래밍의 일반화 대상 ▶ 데이터 형식 (Data Type)일반화

deff-dev.tistory.com

람다식(Lambda Expression)이 무엇인지 설명해주세요.

(input-parameters) => expression // 식 람다
(input-parameters) => { <sequence-of-statements> } // 문 람다

Func<int, int> square = x => x * x; // 식 람다
Action<string> greet = name => { Console.WriteLine("Hello, " + name); }; // 문 람다
  • 익명 메소드를 만들기 위해 람다 선언 연산자 (⇒)를 사용하는 식으로, 식이 본문으로 포함된 식 람다, 문 블록이 본문으로 포함된 문 람다가 있다.

LINQ란 무엇인가요?

int[] numbers = { 1, 2, 3, 4, 5 };

// 쿼리문 형태
var evenNumbers = from num in numbers
                  where num % 2 == 0
                  select num;

// 람다식 형태
var evenNumbersLambda = numbers.Where(num => num % 2 == 0);
  • c# 언어에서 쿼리 기능을 사용하는 것으로 데이터를 빠르고 편리하게 추출 및 처리할 수 있다.
  • Linq == (SQL + 람다식)
  • Linq는 데이터 그룹화가 강점이다.

리플렉션(Reflection)이 뭔지, 사용을 해봤다면 어떤 이유에서 사용했는지 설명해주세요.

  • 정의
    • 리플렉션은 프로그램 실행 중 메소드, 프로퍼티 등 인스턴스의 데이터 타입 정보를 확인하거나 검사하려는 경우 사용되는 기능으로 컴파일 시 알 수 없었던 타입이나 멤버들을 찾아내고 사용할 수 있게 해준다.
  • 사용
using System;
using System.Reflection;

public class Person
{
    public string Name { get; set; }
    private int age;

    public Person(string name, int age)
    {
        Name = name;
        this.age = age;
    }

    private void DisplayAge()
    {
        Console.WriteLine($"Age: {age}");
    }
}

public class ReflectionExample
{
    public static void Main(string[] args)
    {
        // 타입 정보 가져오기
        Type personType = typeof(Person);

        // 생성자 호출
        object personInstance = Activator.CreateInstance(personType, "John", 30);

        // 필드 및 속성 정보 가져오기
        PropertyInfo nameProperty = personType.GetProperty("Name");
        FieldInfo ageField = personType.GetField("age", BindingFlags.NonPublic | BindingFlags.Instance);

        // 값 설정 및 가져오기
        nameProperty.SetValue(personInstance, "Jane");
        Console.WriteLine(nameProperty.GetValue(personInstance)); // Output: Jane

        // 비공개 메서드 호출
        MethodInfo displayAgeMethod = personType.GetMethod("DisplayAge", BindingFlags.NonPublic | BindingFlags.Instance);
        displayAgeMethod.Invoke(personInstance, null); // Output: Age: 30
    }
}

  • 데이터 타입의 정보(예: 필드, 속성, 메서드)를 확인하거나, 동적으로 객체의 멤버/필드에 접근하고 수정할 수 있다.
  • 리플렉션의 단점에 대해 설명해주세요.
    • 성능 오버헤드
      • 리플렉션은 런타임에 타입 정보를 조회하고 조작하기 때문에 성능에 부담이 될 수 있습니다.
    • 타입 안전성 저하
      • 컴파일 시에 타입 체크가 이루어지지 않기 때문에 런타임 오류가 발생할 수 있습니다.
    • 복잡성 증가
      • 리플렉션을 사용하는 코드는 일반적으로 더 복잡하고 유지보수가 어려울 수 있습니다.

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. 다음 코드에서 제네릭을 사용한 부분을 식별하고, 해당 코드가 제네릭을 사용하지 않았을 때 발생할 수 있는 문제점에 대해 설명하세요. 
    • Box 클래스가 제네릭을 사용한 제네릭 클래스이다.
    • 제네릭을 사용하지 않는다면 value의 데이터 타입이 변할 때마다 데이터 타입만 다른 중복 클래스를 만들어줘야한다.
  2. 아래 코드가 어떤 기능을 하는지, 어떤 방식으로 동작하는지 간단하게 설명해주세요.
public static T Max<T>(T a, T b) where T : IComparable<T> { return a.CompareTo(b) > 0 ? a : b; }
  • IComparable를 상속받는 데이터 타입의 입력 값 둘 중 큰 변수를 반환하는 정적 일반화 함수이다.
  • 제네릭을 사용하여 어떤 데이터 타입이든 대응가능하게 작성하여 코드 재사용성과 타입 안정성을 높일 수 있다.