ホームページ >バックエンド開発 >C#.Net チュートリアル >C# プログラミングの基礎 ジェネリック メソッドの分析 (パート 1)
C#2.0 ではジェネリックの機能が導入されました。ジェネリックの導入により、C# の活力はある程度まで大幅に強化され、C#1.0 では複雑なコードを記述する必要があったいくつかの機能を完成させることができます。しかし、開発者として、私はジェネリックに対して愛憎の感情を抱いています。私が気に入っているのは、その強力な機能とこの機能によってもたらされる効率の向上ですが、嫌いなのは、ジェネリックが複雑になると、非常に複雑な構文構造が表示されることです。 。
この複雑さは、初心者だけでなく、開発経験のある一部の .NET 開発者にとっても習得が難しい機能です。
次に、C# 2.0 に追加された機能であるジェネリックを見てみましょう。
1. ジェネリックスの基本機能の概要
実際のプロジェクト開発では、パラメーターの型と戻り値の型としてオブジェクトを使用する API は、ある時点で強力な型変換を必要とする場合があります。強い型変換に関して、多くの開発者の最初の反応は「効率」であると推測されます。強い型付けの長所と短所は、主にユーザーが使用する環境に依存します。絶対的な悪いものや良いものはありません。強い型付けについては、この記事の焦点ではないので、詳しくは紹介しません。
ジェネリックは、別の形式のコード再利用、つまり「アルゴリズム再利用」をサポートする CLR と C# によって提供される特別なメカニズムです。ジェネリックは、型とメソッドのパラメーター化を実装し、パラメーターで使用する型をユーザーに指示することもできます。
ジェネリックによってもたらされる利点: コンパイル時のチェックの改善、コードで直接表現できる情報の増加、IDE サポートの追加、およびパフォーマンスの向上。異なるタイプを区別できない通常の API を使用することは、動的環境でその API にアクセスすることと同じであるのに、なぜジェネリックがこれほど多くのメリットをもたらすのか疑問に思う人もいるかもしれません。
CLR はジェネリック参照とジェネリック値型の作成を許可しますが、ジェネリック列挙型の作成は許可しません。CLR はジェネリック インターフェイスとジェネリック デリゲートの作成を許可します。CLR は参照型、値のジェネリック メソッドの定義を許可します。タイプまたはインターフェイス。ジェネリック型またはメソッドを定義する場合、その型に指定された変数 (T など) は型パラメーターと呼ばれます。 (T は変数名であり、T はデータ型が使用できるソース コード内のどこでも使用できます。) C# では、ジェネリック パラメーター変数は T になるか、少なくとも大文字の T で始まります。
2. ジェネリック クラス、ジェネリック インターフェイス、ジェネリック デリゲートの概要
1. ジェネリック クラス
ジェネリック型は型であるため、任意の型から派生できます。ジェネリック型を使用して型引数を指定すると、ジェネリックの派生元の型から派生した新しい型オブジェクトを CLR に定義することになります。
ジェネリック型パラメーターを使用するメソッド。JIT コンパイル中に、CLR は IL を取得し、指定された型引数に置き換えて、適切なネイティブ コードを作成します。
ジェネリック型パラメーターに型引数が指定されていない場合、ジェネリック型はバインドされていません。 type 引数が指定されている場合、その型は構築された型になります。
構築型には開発型またはクローズ型があり、開発型にはクラス 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: を提供します。 collection の場合、コレクションの項目はキーとして使用されるタイプです。
[__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# プログラミングの基礎のジェネリック メソッド分析 (パート 1) の内容です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。