개발자는 암시적이든 명시적으로든 .NET에서 항상 제네릭을 사용합니다. .NET에서 LINQ를 사용할 때 IEnumerable<T>을(를) 작업하고 있다는 것을 알아차린 적이 있었나요? 또는 Entity Framework를 사용하여 데이터베이스와 통신하기 위한 "제네릭 리포지토리"의 온라인 샘플을 본 적이 있다면 대부분의 메서드가 반환 IQueryable<T>되는 것을 보셨나요? 이러한 예제에서 T 가 무엇이고 왜 거기에 있는지 궁금했을 것입니다.
.NET Framework 2.0에서 처음 도입된 제네릭은 기본적으로 개발자가 실제 데이터 형식에 커밋하지 않고 형식이 안전한 데이터 구조를 정의할 수 있는 "코드 템플릿"입니다. 예를 들어, List<T>는 , List<int>, 또는 List<string> 같은 모든 형식과 함께 선언하고 사용할 수 있는 List<Person>입니다.
제네릭이 유용한 이유를 이해하려면 제네릭 ArrayList을 추가하기 전과 후에 특정 클래스를 살펴보겠습니다. .NET Framework 1.0에서는 ArrayList 요소가 형식 Object이었습니다. 컬렉션에 추가된 모든 요소가 자동으로 .로 Object변환되었습니다. 목록에서 요소를 읽을 때도 마찬가지입니다. 이 과정은 박싱 및 언박싱으로 알려져 있으며, 성능에 영향을 미칩니다. 그러나 성능 외에도 컴파일 시간에 목록의 데이터 형식을 확인할 수 있는 방법이 없으므로 일부 취약한 코드가 생성됩니다. 제네릭은 목록의 각 인스턴스가 포함할 데이터 형식을 정의하여 이 문제를 해결합니다. 오직 List<int>에는 정수만 추가할 수 있고 List<Person>에는 오직 Persons만 추가할 수 있습니다.
제네릭은 런타임에도 사용할 수 있습니다. 런타임은 사용 중인 데이터 구조의 유형을 알고 메모리에 보다 효율적으로 저장할 수 있습니다.
다음 예제는 런타임에 데이터 구조 형식을 아는 효율성을 보여 주는 작은 프로그램입니다.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace GenericsExample {
class Program {
static void Main(string[] args) {
//generic list
List<int> ListGeneric = new List<int> { 5, 9, 1, 4 };
//non-generic list
ArrayList ListNonGeneric = new ArrayList { 5, 9, 1, 4 };
// timer for generic list sort
Stopwatch s = Stopwatch.StartNew();
ListGeneric.Sort();
s.Stop();
Console.WriteLine($"Generic Sort: {ListGeneric} \n Time taken: {s.Elapsed.TotalMilliseconds}ms");
//timer for non-generic list sort
Stopwatch s2 = Stopwatch.StartNew();
ListNonGeneric.Sort();
s2.Stop();
Console.WriteLine($"Non-Generic Sort: {ListNonGeneric} \n Time taken: {s2.Elapsed.TotalMilliseconds}ms");
Console.ReadLine();
}
}
}
이 프로그램은 다음과 유사한 출력을 생성합니다.
Generic Sort: System.Collections.Generic.List`1[System.Int32]
Time taken: 0.0034ms
Non-Generic Sort: System.Collections.ArrayList
Time taken: 0.2592ms
여기에서 가장 먼저 알 수 있는 것은 제네릭 목록을 정렬하는 것이 제네릭이 아닌 목록을 정렬하는 것보다 훨씬 빠르다는 것입니다. 제네릭 목록의 형식은 고유하지만([System.Int32]), 제네릭이 아닌 목록의 형식은 일반화됩니다. 런타임은 제네릭 List<int> 이 형식 Int32임을 알고 있으므로 메모리의 기본 정수 배열에 목록 요소를 저장할 수 있지만, 제네릭 ArrayList 이 아닌 사용자는 각 목록 요소를 개체로 캐스팅해야 합니다. 이 예제에서와 같이 추가 캐스트는 시간이 걸리고 목록 정렬 속도가 느려집니다.
제네릭 유형을 아는 런타임의 추가적인 이점은 더 나은 디버깅 환경입니다. C#에서 제네릭을 디버깅할 때 각 요소가 데이터 구조에 있는 형식을 알 수 있습니다. 제네릭이 없으면 각 요소의 형식을 알 수 없습니다.
참고하십시오
.NET