C# 2.0에는 제네릭의 도입으로 인해 C#의 생명력이 어느 정도 크게 향상되었으며, C# 1.0에서 복잡한 코드를 작성해야 했던 일부 기능을 완성할 수 있습니다. 하지만 개발자로서 나는 Generics에 대해 애증의 관계를 가지고 있습니다. 제가 좋아하는 것은 강력한 기능과 이 기능으로 인한 효율성 향상이지만, 제가 싫어하는 것은 Generic이 복잡할 때 상당히 복잡한 구문 구조를 제시한다는 것입니다. .
이러한 복잡성은 초보자뿐만 아니라 개발 경험이 있는 일부 .NET 개발자에게도 익히기 쉽지 않은 기능입니다.
다음으로 C# 2.0에 추가된 기능인 제네릭을 살펴보겠습니다.
1. Generic의 기본 기능 개요
실제 프로젝트 개발에서는 모든 API만 사용하면 됩니다. 매개변수 유형과 반환 유형을 사용하면 어떤 시점에서는 강력한 유형 변환이 필요할 수 있습니다. 강력한 유형 변환에 대해 많은 개발자의 첫 번째 반응은 "효율성"이라고 추정됩니다. 강력한 유형의 장점과 단점은 주로 사용자가 사용하는 환경에 따라 결정됩니다. 강한 타이핑에 관한 문제는 이 글의 초점이 아니므로 자세히 소개하지 않겠습니다.
제네릭은 "알고리즘 재사용"이라는 또 다른 형태의 코드 재사용을 지원하는 CLR 및 C#에서 제공하는 특수 메커니즘입니다. 제네릭은 유형 및 메소드의 매개변수화를 구현합니다. 제네릭 유형 및 메소드를 통해 매개변수는 사용자에게 사용할 유형을 알려줄 수도 있습니다.
제네릭이 가져오는 이점: 더 나은 컴파일 타임 검사, 코드에 직접 표현할 수 있는 더 많은 정보, 더 많은 IDE 지원, 더 나은 성능. 어떤 사람들은 제네릭이 왜 그렇게 많은 이점을 가져오는지 궁금해할 수 있습니다. 서로 다른 유형을 구별할 수 없는 일반 API를 사용하는 것은 동적 환경에서 해당 API에 액세스하는 것과 같습니다.
CLR은 일반 참조 및 일반 값 유형의 생성을 허용하지만 일반 열거형의 생성은 허용하지 않으며 CLR은 일반 인터페이스 및 일반 대리자의 생성을 허용하고 CLR은 참조 유형의 생성을 허용합니다. 값 유형 또는 인터페이스 일반 메소드를 정의합니다. 제네릭 형식이나 메서드를 정의할 때 해당 형식에 대해 지정된 모든 변수(예: T)를 형식 매개변수라고 합니다. (T는 변수 이름이고, T는 데이터 유형이 사용될 수 있는 소스 코드의 어느 곳에서나 사용될 수 있습니다.) C#에서 일반 매개변수 변수는 T가 되거나 최소한 대문자 T로 시작합니다.
2. 제네릭 클래스, 제네릭 인터페이스 및 제네릭 대리자 개요
1. 제네릭 클래스
제네릭 유형은 여전히 유형이므로 모든 유형에서 파생될 수 있습니다. 제네릭 형식을 사용하고 형식 인수를 지정하면 제네릭이 파생된 형식에서 파생된 CLR의 새 형식 개체를 정의하게 됩니다.
JIT 컴파일 중에 CLR은 IL을 획득하고 이를 지정된 유형 인수로 바꾼 다음 적절한 네이티브 코드를 생성합니다.
일반 유형 매개변수에 대해 유형 인수가 제공되지 않으면 일반 유형이 바인딩 해제됩니다. 유형 인수가 지정된 경우 유형은 생성된 유형입니다.
구성된 유형은 개방형이거나 폐쇄형일 수 있습니다. 개방형 유형에는 ixngcanshu 클래스도 포함되는 반면, 폐쇄형 유형은 개방형이 아니며 유형의 모든 부분이 명시적입니다. 모든 코드는 실제로 둘러싸는 생성된 유형의 컨텍스트 내에서 실행됩니다.
.NET에서 일반 클래스의 적용은 주로 컬렉션 클래스에 있으며 대부분의 컬렉션 클래스는 System.Collections.Generic 및 System.Collections.ObjectModel 클래스에 있습니다. 다음은 일반 컬렉션 클래스에 대한 간략한 소개입니다.
(1).SynchronizedCollection: 일반 매개 변수에 의해 지정된 유형의 개체를 요소로 포함하는 스레드로부터 안전한 컬렉션을 제공합니다.
[ComVisible(false)] public class SynchronizedCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable { /// <summary> /// 初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 类的新实例。 /// </summary> public SynchronizedCollection(); /// <summary> /// 通过用于对线程安全集合的访问进行同步的对象来初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 类的新实例。 /// </summary> /// <param name="syncRoot">用于对线程安全集合的访问进行同步的对象。</param><exception cref="T:System.ArgumentNullException"> <paramref name="syncRoot"/> 为 null。</exception> public SynchronizedCollection(object syncRoot); /// <summary> /// 使用指定的可枚举元素列表和用于对线程安全集合的访问进行同步的对象来初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 类的新实例。 /// </summary> /// <param name="syncRoot">用于对线程安全集合的访问进行同步的对象。</param> <param name="list">用于初始化线程安全集合的元素的 <see cref="T:System.Collections.Generic.IEnumerable`1"/> 集合。</param> <exception cref="T:System.ArgumentNullException"><paramref name="syncRoot"/> 或 <paramref name="list"/> 为 null。</exception> public SynchronizedCollection(object syncRoot, IEnumerable<T> list); /// <summary> /// 使用指定的元素数组和用于对线程安全集合的访问进行同步的对象来初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 类的新实例。 /// </summary> /// <param name="syncRoot">用于对线程安全集合的访问进行同步的对象。</param> <param name="list">用于初始化线程安全集合的 <paramref name="T"/> 类型元素的 <see cref="T:System.Array"/>。</param> <exception cref="T:System.ArgumentNullException"><paramref name="syncRoot"/> 或 <paramref name="list"/> 为 null。</exception> public SynchronizedCollection(object syncRoot, params T[] list); /// <summary> /// 将项添加到线程安全只读集合中。 /// </summary> /// <param name="item">要添加到集合的元素。</param> <exception cref="T:System.ArgumentException">设置的值为 null,或者不是集合的正确泛型类型 <paramref name="T"/>。</exception> public void Add(T item); /// <summary> /// 从集合中移除所有项。 /// </summary> public void Clear(); /// <summary> /// 从特定索引处开始,将集合中的元素复制到指定的数组。 /// </summary> /// <param name="array">从集合中复制的 <paramref name="T "/>类型元素的目标 <see cref="T:System.Array"/>。</param> <param name="index">复制开始时所在的数组中的从零开始的索引。</param> public void CopyTo(T[] array, int index); /// <summary> /// 确定集合是否包含具有特定值的元素。 /// </summary> /// /// <returns> /// 如果在集合中找到元素值,则为 true;否则为 false。 /// </returns> /// <param name="item">要在集合中定位的对象。</param> <exception cref="T:System.ArgumentException">设置的值为 null,或者不是集合的正确泛型类型 <paramref name="T"/>。</exception> public bool Contains(T item); /// <summary> /// 返回一个循环访问同步集合的枚举数。 /// </summary> /// /// <returns> /// 一个 <see cref="T:System.Collections.Generic.IEnumerator`1"/>,用于访问集合中存储的类型的对象。 /// </returns> public IEnumerator<T> GetEnumerator(); /// <summary> /// 返回某个值在集合中的第一个匹配项的索引。 /// </summary> /// /// <returns> /// 该值在集合中的第一个匹配项的从零开始的索引。 /// </returns> /// <param name="item">从集合中移除所有项。</param><exception cref="T:System.ArgumentException">设置的值为 null,或者不是集合的正确泛型类型 <paramref name="T"/>。</exception> public int IndexOf(T item); /// <summary> /// 将一项插入集合中的指定索引处。 /// </summary> /// <param name="index">要从集合中检索的元素的从零开始的索引。</param><param name="item">要作为元素插入到集合中的对象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的项数。</exception> <exception cref="T:System.ArgumentException">设置的值为 null,或者不是集合的正确泛型类型 <paramref name="T"/>。</exception> public void Insert(int index, T item); /// <summary> /// 从集合中移除指定项的第一个匹配项。 /// </summary> /// /// <returns> /// 如果从集合中成功移除了项,则为 true;否则为 false。 /// </returns> /// <param name="item">要从集合中移除的对象。</param> public bool Remove(T item); /// <summary> /// 从集合中移除指定索引处的项。 /// </summary> /// <param name="index">要从集合中检索的元素的从零开始的索引。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的项数。</exception> public void RemoveAt(int index); /// <summary> /// 从集合中移除所有项。 /// </summary> protected virtual void ClearItems(); /// <summary> /// 将一项插入集合中的指定索引处。 /// </summary> /// <param name="index">集合中从零开始的索引,在此处插入对象。</param><param name="item">要插入到集合中的对象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的项数。</exception> <exception cref="T:System.ArgumentException">设置的值为 null,或者不是集合的正确泛型类型 <paramref name="T"/>。</exception> protected virtual void InsertItem(int index, T item); /// <summary> /// 从集合中移除指定 <paramref name="index"/> 处的项。 /// </summary> /// <param name="index">要从集合中检索的元素的从零开始的索引。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的项数。</exception> protected virtual void RemoveItem(int index); /// <summary> /// 使用另一项替换指定索引处的项。 /// </summary> /// <param name="index">要替换的对象的从零开始的索引。</param><param name="item">要替换的对象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的项数。</exception> protected virtual void SetItem(int index, T item); /// <summary> /// 返回一个循环访问同步集合的枚举数。 /// </summary> /// /// <returns> /// 一个 <see cref="T:System.Collections.Generic.IEnumerator`1"/>,用于访问集合中存储的类型的对象。 /// </returns> IEnumerator IEnumerable.GetEnumerator(); /// <summary> /// 从特定索引处开始,将集合中的元素复制到指定的数组。 /// </summary> /// <param name="array">从集合中复制的 <paramref name="T"/> 类型元素的目标 <see cref="T:System.Array"/>。</param> <param name="index">复制开始时所在的数组中的从零开始的索引。</param> void ICollection.CopyTo(Array array, int index); /// <summary> /// 向集合中添加一个元素。 /// </summary> /// /// <returns> /// 新元素的插入位置。 /// </returns> /// <param name="value">要添加到集合中的对象。</param> int IList.Add(object value); /// <summary> /// 确定集合是否包含具有特定值的元素。 /// </summary> /// <returns> /// 如果在集合中找到元素 <paramref name="value"/>,则为 true;否则为 false。 /// </returns> /// <param name="value">要在集合中定位的对象。</param><exception cref="T:System.ArgumentException"><paramref name="value"/> 不是集合所含类型的对象。</exception> bool IList.Contains(object value); /// <summary> /// 确定集合中某个元素的从零开始的索引。 /// </summary> /// /// <returns> /// 如果在集合中找到,则为 <paramref name="value"/> 的索引;否则为 -1。 /// </returns> /// <param name="value">集合中要确定其索引的元素。</param> int IList.IndexOf(object value); /// <summary> /// 将某个对象插入到集合中的指定索引处。 /// </summary> /// <param name="index">从零开始的索引,将在该位置插入 <paramref name="value"/>。</param><param name="value">要在集合中插入的对象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的项数。</exception> <exception cref="T:System.ArgumentException">设置的 <paramref name="value"/> 为 null,或者不是集合的正确泛型类型 <paramref name="T"/>。</exception> void IList.Insert(int index, object value); /// <summary> /// 从集合中移除作为元素的指定对象的第一个匹配项。 /// </summary> /// <param name="value">要从集合中移除的对象。</param> void IList.Remove(object value); }
( 2).KeyedByTypeCollection: 항목이 키로 사용되는 유형인 컬렉션을 제공합니다.
[__DynamicallyInvokable] public class KeyedByTypeCollection<TItem> : KeyedCollection<Type, TItem> { /// <summary> /// 初始化 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 类的新实例。 /// </summary> public KeyedByTypeCollection(); /// <summary> /// 根据指定的对象枚举初始化 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 类的新实例。 /// </summary> /// <param name="items">泛型类型 <see cref="T:System.Object"/> 的 <see cref="T:System.Collections.Generic.IEnumerable`1"/>,用于初始化集合。</param> <exception cref="T:System.ArgumentNullException"><paramref name="items"/> 为 null。</exception> public KeyedByTypeCollection(IEnumerable<TItem> items); /// <summary> /// 返回集合中第一个具有指定类型的项。 /// </summary> /// /// <returns> /// 如果为引用类型,则返回类型 <paramref name="T"/> 的对象;如果为值类型,则返回类型 <paramref name="T"/> 的值。 如果集合中不包含类型 <paramref name="T"/> 的对象,则返回类型的默认值:如果是引用类型,默认值为 null;如果是值类型,默认值为 0。 /// </returns> /// <typeparam name="T">要在集合中查找的项的类型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public T Find<T>(); /// <summary> /// 从集合中移除具有指定类型的对象。 /// </summary> /// /// <returns> /// 从集合中移除的对象。 /// </returns> /// <typeparam name="T">要从集合中移除的项的类型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public T Remove<T>(); /// <summary> /// 返回 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 中包含的类型 <paramref name="T"/> 的对象的集合。 /// </summary> /// /// <returns> /// 一个类型 <paramref name="T"/> 的 <see cref="T:System.Collections.ObjectModel.Collection`1"/>,包含来自原始集合的类型 <paramref name="T"/> 的对象。 /// </returns> /// <typeparam name="T">要在集合中查找的项的类型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public Collection<T> FindAll<T>(); /// <summary> /// 从集合中移除所有具有指定类型的元素。 /// </summary> /// /// <returns> /// <see cref="T:System.Collections.ObjectModel.Collection`1"/>,包含来自原始集合的类型 <paramref name="T"/> 的对象。 /// </returns> /// <typeparam name="T">要从集合中移除的项的类型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public Collection<T> RemoveAll<T>(); /// <summary> /// 获取集合中包含的某个项的类型。 /// </summary> /// /// <returns> /// 集合中指定的 <paramref name="item"/> 的类型。 /// </returns> /// <param name="item">集合中要检索其类型的项。</param><exception cref="T:System.ArgumentNullException"><paramref name="item"/> 为 null。</exception> [__DynamicallyInvokable] protected override Type GetKeyForItem(TItem item); /// <summary> /// 在集合中的特定位置插入一个元素。 /// </summary> /// <param name="index">从零开始的索引,应在该位置插入 <paramref name="item"/>。</param><param name="item">要在集合中插入的对象。</param> <exception cref="T:System.ArgumentNullException"><paramref name="item"/> 为 null。</exception> [__DynamicallyInvokable] protected override void InsertItem(int index, TItem item); /// <summary> /// 使用一个新对象替换指定索引处的项。 /// </summary> /// <param name="index">要替换的 <paramref name="item"/> 的从零开始的索引。</param><param name="item">要添加到集合中的对象。</param> <exception cref="T:System.ArgumentNullException"><paramref name="item"/> 为 null。</exception> [__DynamicallyInvokable] protected override void SetItem(int index, TItem item); }
CLR은 모든 유형의 개체가 유형이 안전한 방식으로 콜백 메서드에 전달될 수 있도록 하는 일반 위임을 지원합니다. 일반 대리자를 사용하면 박싱을 수행하지 않고도 자식 유형 인스턴스를 콜백 메서드에 전달할 수 있습니다. 대리자 타이밍은 생성자, Invlke 메서드, BeginInvoke 메서드 및 EndInvoke 메서드의 4가지 메서드만 제공합니다. 형식 매개 변수를 지정하는 대리자 형식을 정의하면 컴파일러는 대리자 클래스의 메서드를 정의하고 메서드의 매개 변수 형식과 값 형식을 지정된 형식 매개 변수로 바꿉니다.
위 내용은 C# 프로그래밍 기초 중 Generic Method Analysis(1부) 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(m.sbmmt.com)를 참고해주세요!