search
HomeBackend DevelopmentC#.Net TutorialAnalysis of generic methods in C# programming basics (Part 1)

C#2.0 introduced the feature of generics. Due to the introduction of generics, the vitality of C# has been greatly enhanced to a certain extent. It can complete some functions that required writing complex code in C#1.0. But as a developer, I have a love-hate relationship with generics. What I love is its powerful functions and the efficiency improvements brought by this feature, but what I hate is that when generics are complex, they will present quite complicated syntax structures. .


This complexity is not only for beginners, but also a feature that is not easy to master for some .NET developers with development experience.


Next let’s take a look at the features added in C# 2.0: generics.


1. Overview of the basic characteristics of generics


In actual project development, any API only needs to use object as The use of parameter types and return types may involve strong type conversion at some point. When it comes to strong type conversion, it is estimated that the first reaction of many developers is "efficiency". The pros and cons of strong typing mainly depend on the environment in which the user uses it. There is no absolute bad thing or good thing in the world. Regarding strong typing, The issue is not the focus of this article and I will not introduce it in detail.


Generics are a special mechanism provided by the CLR and C# that support another form of code reuse, namely "algorithm reuse". Generics implement parameterization of types and methods. Generic types and methods can also let parameters tell users what type to use.


Benefits brought by generics: better compile-time checking, more information that can be directly expressed in the code, more IDE support, better performance. Some people may wonder why generics bring so many benefits. Using a regular API that cannot distinguish between different types is equivalent to accessing that API in a dynamic environment.

CLR allows the creation of generic references and generic value types, but does not allow the creation of generic enumerations, and the CLR allows the creation of generic interfaces and generic delegates. The CLR allows the creation of generic reference types, value types, or interfaces. Define generic methods. When defining a generic type or method, any variables (such as T) specified for the type are called type parameters. (T is a variable name, and T can be used anywhere in the source code that a data type can be used.) In C#, generic parameter variables either become T, or at least start with a capital T.

2. Overview of generic classes, generic interfaces and generic delegates

1. Generic classes

Generic types are still types, so they can be derived from any type . When you use a generic type and specify type arguments, you are defining a new type object in the CLR that is derived from the type from which the generic is derived.

One method of using generic type parameters During JIT compilation, the CLR obtains the IL, replaces it with the specified type argument, and then creates the appropriate native code.

If no type arguments are provided for a generic type parameter, then the generic type is unbound. If a type argument is specified, the type is a constructed type.

Constructed types can be open or closed. Open types also contain a class ixngcanshu, while closed types are not open and every part of the type is explicit. All code is actually executed within the context of an enclosing constructed type.

The application of generic classes in .NET is mainly in collection classes, and most collection classes are in the System.Collections.Generic and System.Collections.ObjectModel classes. The following is a brief introduction to a generic collection class:

(1).SynchronizedCollection: Provides a thread-safe collection that contains objects of the type specified by the generic parameters as elements.

[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: Provides a collection whose items are the types used as keys.

[__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 supports generic delegation to ensure that any type of object can be passed to a callback method in a type-safe manner. Generic delegates allow a child type instance to be passed to a callback method without performing any boxing. The delegate timing provides only 4 methods: a constructor, an Invlke method, a BeginInvoke method and an EndInvoke method. If you define a delegate type that specifies type parameters, the compiler will define the method of the delegate class and replace the method's parameter type and value type with the specified type parameters.

The above is the content of Generic Method Analysis (Part 1) of C# Programming Basics. For more related content, please pay attention to the PHP Chinese website (m.sbmmt.com)!


Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Blazor Server vs Blazor WebAssembly: Choosing the Right Hosting ModelBlazor Server vs Blazor WebAssembly: Choosing the Right Hosting ModelAug 26, 2025 am 08:45 AM

BlazorServer is suitable for scenarios with low user volume, low latency and strong security. The core logic runs on the server side, dependent on the network but starts quickly; BlazorWebAssembly is suitable for scenarios with high scalability, offline use, and independent deployment. The code runs on the client side, and the first screen loads slowly but the interaction is smooth. 1. In terms of working principle, BlazorServer processes logic and pushes updates on the server through SignalR, while WebAssembly downloads .NET runtime in the browser and executes locally. 2. In terms of applicable scenarios, Server is suitable for projects with poor equipment performance and need to be launched quickly; WebAssembly is suitable for public network SaaS, PWA, and API driver architectures.

Implementing the Strategy Pattern in C# for Flexible AlgorithmsImplementing the Strategy Pattern in C# for Flexible AlgorithmsAug 26, 2025 am 07:22 AM

Definethestrategyinterfacetodeclareacommonmethodforallalgorithms.2.Implementconcretestrategiesthatadheretotheinterface,eachprovidingadifferentalgorithm.3.Createacontextclassthatholdsareferencetoastrategyanddelegatesthetasktoit.4.Usethepatternbyinstan

What is the role of the this keyword in C#?What is the role of the this keyword in C#?Aug 25, 2025 pm 04:43 PM

In C#, this keyword has four main uses. 1. Reference the current instance of the class to resolve conflicts between the fields and parameters, such as this.name assignment in the constructor; 2. Pass the current object as a parameter to other methods, such as OrderProcessor.Process(this); 3. Implement chain calls of the constructor through this to reduce duplicate code, such as the constructor with parameter without arguments; 4. Use this to modify the first parameter in the extension method to make the method look like an instance method, such as the WordCount extension method of type string.

How to make an HTTP GET request using HttpClient in C#?How to make an HTTP GET request using HttpClient in C#?Aug 25, 2025 pm 04:42 PM

When sending HTTPGET requests using HttpClient in C#, the instance should be multiplexed, the response should be processed correctly, and the request header should be added. It is recommended to create an HttpClient instance as a singleton or static field to avoid socket exhaustion; sending a GET request, you can use GetStringAsync to get string results or GetAsync to process status code and response content; you need to add authentication information such as APIKey through DefaultRequestHeaders; at the same time, you should pay attention to exception handling, set up BaseAddress to simplify URL management, and it is recommended to use IHttpClientFactory to manage client instances to optimize resources.

How to create a Windows Service in C#?How to create a Windows Service in C#?Aug 24, 2025 pm 05:27 PM

To create a Windows service, you need to use the ServiceBase class and follow the steps to implement it. 1. Create a WindowsService project in VisualStudio and inherit the ServiceBase class; 2. Write service logic such as timing tasks or listening operations in the OnStart() and OnStop() methods; 3. Add the installer component to set Account, ServiceName and StartType properties to register the service; 4. Use the installutil command to install or uninstall the service and check the service manager to confirm the registration status; 5. Debug by attaching a debugger or manually attaching it to the process. Mastering these steps can help you realize background task processing and

Entity Framework Core vs. Dapper: A Performance and Productivity ShowdownEntity Framework Core vs. Dapper: A Performance and Productivity ShowdownAug 24, 2025 pm 05:00 PM

DapperisfasterthanEFCoreduetominimaloverheadanddirectSQLexecution,makingitidealforperformance-criticalscenarios.2.EFCoreofferssuperiorproductivitywithLINQ,changetracking,migrations,andrelationshipmanagement,acceleratingdevelopment.3.ChooseDapperforhi

Exploring C# 12's New Features: Primary Constructors and Collection ExpressionsExploring C# 12's New Features: Primary Constructors and Collection ExpressionsAug 24, 2025 am 10:37 AM

C#12introducesprimaryconstructorsandcollectionexpressionsthatsignificantlyenhancecodeclarityanddeveloperefficiency.1.Primaryconstructorsallowdeclaringconstructorparametersdirectlyonclassesorstructs,reducingboilerplatebyenablinginlineinitializationand

Optimizing .NET Garbage Collection: A Deep Dive for Senior DevelopersOptimizing .NET Garbage Collection: A Deep Dive for Senior DevelopersAug 24, 2025 am 12:33 AM

To optimize .NET garbage collection, you should first clarify whether to use ServerGC or WorkstationGC: ServerGC is suitable for multi-core server applications to improve throughput. The configuration method is to set "System.GC.Server":true in runtimeconfig.json; use it with caution in 1-2 core low-configuration environments. Secondly, select GC mode according to the delay requirements: Batch mode is suitable for high-throughput scenarios, Interactive is used for regular responsive services, LowLatency mode can temporarily reduce pause time, but exit in time after use to prevent memory overflow. Next, understand the intergenerational recycling mechanism to avoid short-lived life cycle objects

See all articles

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Hot Topics