C# 泛型(Generics)詳解

泛型是 C# 2.0 引入的核心特性,它允許在定義類、接口、方法、委托等時使用未指定的類型參數,在使用時再指定具體類型。這種機制可以顯著提高代碼的復用性、類型安全性和性能。

一、泛型的核心概念
  1. 類型參數化
    泛型允許將類型作為 "參數" 傳遞給類、方法等,就像方法可以接受數值參數一樣。例如,List<T>?中的?T?就是類型參數,使用時可以指定為?List<int>List<string>?等。

  2. 編譯時類型檢查
    泛型在編譯階段就會進行類型驗證,避免了運行時的類型轉換錯誤。例如,List<int>?只能存儲?int?類型,編譯器會阻止添加字符串等其他類型。

  3. 消除裝箱 / 拆箱操作
    對于值類型(如?intdouble),非泛型集合(如?ArrayList)會將值類型裝箱為?object,取出時再拆箱,造成性能損耗。泛型集合(如?List<int>)直接存儲值類型,避免了這一過程。

  4. 代碼復用
    一套泛型代碼可以適配多種數據類型,無需為每種類型重復編寫邏輯(如排序、查找等)。

二、泛型的基本使用
1. 泛型類(Generic Classes)

泛型類是最常用的泛型形式,定義時在類名后添加?<類型參數>,使用時指定具體類型。

// 定義泛型類
public class MyGenericClass<T>
{private T _value;public MyGenericClass(T value){_value = value;}public T GetValue(){return _value;}public void SetValue(T value){_value = value;}
}// 使用泛型類
var intContainer = new MyGenericClass<int>(10);
int intValue = intContainer.GetValue(); // 10var stringContainer = new MyGenericClass<string>("Hello");
string stringValue = stringContainer.GetValue(); // "Hello"
2. 泛型方法(Generic Methods)

泛型方法可以在普通類或泛型類中定義,方法名后添加?<類型參數>,調用時可顯式或隱式指定類型。

public class GenericMethodExample
{// 定義泛型方法public T Max<T>(T a, T b) where T : IComparable<T>{return a.CompareTo(b) > 0 ? a : b;}
}// 使用泛型方法
var example = new GenericMethodExample();
int maxInt = example.Max(5, 10); // 10(隱式推斷類型為int)
string maxStr = example.Max<string>("apple", "banana"); // "banana"(顯式指定類型)
3. 泛型接口(Generic Interfaces)

泛型接口與泛型類類似,常用于定義集合、比較器等具有通用性的契約。?

// 定義泛型接口
public interface IRepository<T>
{T GetById(int id);void Add(T item);void Update(T item);void Delete(int id);
}// 實現泛型接口(以用戶倉儲為例)
public class UserRepository : IRepository<User>
{public User GetById(int id) { /* 實現 */ }public void Add(User item) { /* 實現 */ }public void Update(User item) { /* 實現 */ }public void Delete(int id) { /* 實現 */ }
}
4. 泛型委托(Generic Delegates)

泛型委托允許定義可接受不同類型參數的委托,C# 內置的?Func<T>Action<T>?就是典型例子。

// 定義泛型委托
public delegate T Transformer<T>(T input);// 使用泛型委托
public class DelegateExample
{public static int Square(int x) => x * x;public static string ToUpper(string s) => s.ToUpper();
}// 調用
Transformer<int> intTransformer = DelegateExample.Square;
int result = intTransformer(5); // 25Transformer<string> stringTransformer = DelegateExample.ToUpper;
string upperStr = stringTransformer("hello"); // "HELLO"
5. 泛型約束(Constraints)

泛型約束用于限制類型參數的范圍,確保類型參數滿足特定條件(如必須實現某接口、必須是引用類型等)。常用約束如下:

約束語法說明
where T : structT?必須是值類型(非?Nullable<T>
where T : class
T?必須是引用類型
where T : new()T?必須有公共無參構造函數
where T : 基類名T?必須是指定基類或其派生類
where T : 接口名
T?必須實現指定接口
where T : UT?必須是?U?或其派生類(用于多參數)

示例:

// 約束T必須實現IComparable<T>接口
public class GenericWithConstraint<T> where T : IComparable<T>
{public T FindMax(T[] items){if (items == null || items.Length == 0)throw new ArgumentException("數組不能為空");T max = items[0];foreach (var item in items){if (item.CompareTo(max) > 0)max = item;}return max;}
}
6. 泛型集合(Generic Collections)

.NET Framework 提供了豐富的泛型集合類(位于?System.Collections.Generic?命名空間),替代了非泛型集合(如?ArrayListHashtable):

  • List<T>:動態數組,替代?ArrayList
  • Dictionary<TKey, TValue>:鍵值對集合,替代?Hashtable
  • HashSet<T>:無序唯一元素集合
  • Queue<T>:先進先出(FIFO)隊列
  • Stack<T>:后進先出(LIFO)棧

示例:

using System.Collections.Generic;// 使用List<T>
var numbers = new List<int> { 1, 2, 3 };
numbers.Add(4);
int first = numbers[0];// 使用Dictionary<TKey, TValue>
var personAges = new Dictionary<string, int>
{{ "Alice", 30 },{ "Bob", 25 }
};
int aliceAge = personAges["Alice"];
三、泛型的高級特性
1. 泛型類型參數的協變與逆變
  • 協變(Covariance):允許將泛型類型參數從派生類隱式轉換為基類,使用?out?關鍵字標記(僅適用于接口和委托)。
  • 逆變(Contravariance):允許將泛型類型參數從基類隱式轉換為派生類,使用?in?關鍵字標記(僅適用于接口和委托)。

示例:

// 協變接口(out關鍵字)
public interface IEnumerable<out T> { ... }// 逆變接口(in關鍵字)
public interface IComparer<in T> { ... }// 用法
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // 協變:string → objectIComparer<object> objectComparer = new ObjectComparer();
IComparer<string> stringComparer = objectComparer; // 逆變:object → string
2. 靜態字段與泛型

泛型類的靜態字段在不同封閉類型(如?MyClass<int>?和?MyClass<string>)中是獨立的,不會共享:

public class StaticGeneric<T>
{public static int Count { get; set; } = 0;
}// 不同類型的靜態字段獨立
StaticGeneric<int>.Count = 1;
StaticGeneric<string>.Count = 2;
Console.WriteLine(StaticGeneric<int>.Count); // 1(與string的Count無關)

List<int>?本質上是泛型類?List<T>?的一個實例化版本,它依賴于泛型機制才能存在。如果沒有?List<T>?這個泛型定義,就無法通過傳入?int?得到?List<int>

T?是泛型的 "模板參數",而?int?是填充這個模板的 "實際參數"。List<int>?是泛型機制的產物,因此它是泛型集合的典型應用。

3. 泛型類型的反射

可以通過反射獲取泛型類型的信息,如類型參數、約束等:

Type listType = typeof(List<int>);
if (listType.IsGenericType)
{Type genericTypeDefinition = listType.GetGenericTypeDefinition(); // 得到List<T>Type[] typeArguments = listType.GetGenericArguments(); // 得到[int]
}
四、泛型的優勢總結
  1. 類型安全:編譯時檢查類型,避免運行時類型轉換錯誤。
  2. 性能優化:減少裝箱 / 拆箱操作,尤其對值類型更高效。
  3. 代碼復用:一套邏輯適配多種類型,減少重復代碼。
  4. 靈活性:結合約束、協變、逆變等特性,可適應復雜場景。
五、泛型的適用場景
  • 集合類(如自定義列表、字典)
  • 工具類(如轉換器、比較器)
  • 數據訪問層(如通用倉儲模式)
  • 委托和事件(如通用回調函數)
  • 算法實現(如排序、搜索,適用于多種數據類型)

通過泛型,C# 代碼可以在保持類型安全的同時實現高度復用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93200.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93200.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93200.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring中存在兩個相同的Bean是否會報錯?

第一種情況&#xff1a;使用XML的方式設置Bean&#xff0c;這種情況在Spring啟動時就會報錯&#xff0c;因為ID在Spring中是Bean的唯一標識&#xff0c;Spring容器在啟動時會校驗唯一性&#xff0c;一旦發現重復就會報錯。但是如果是在兩個不同的XML文件中定義兩個相同的Bean&a…

【新手入門】Android基礎知識(一):系統架構

目 錄 Android 系統架構圖 1. 應用 2. JAVA API 框架 3. 原生 C/C 庫 4. Android 運行時&#xff08;Android Runtime&#xff09; 5. 硬件抽象層 (HAL) 6. Linux 內核 參考資料 Android 系統架構圖 Android底層內核空間以Linux Kernel作為基石&#xff0c;上層用戶空…

晶振電路的負載電容、電阻參數設計

系列文章目錄 文章目錄系列文章目錄前言一、晶振主要參數二、有源與無源區別三、無源晶振四、有源晶振總結前言 在硬件電路的設計中&#xff0c;晶振電路是必不可少的&#xff0c;它充當了整個電路心臟的作用。在這個晶振電路的設計中負載電容、電阻參數的選型是很重要的&…

電腦上練打字用什么軟件最好:10款打字軟件評測

現在孩子們在電腦上練打字&#xff0c;軟件一搜一大把&#xff0c;可好多家長和老師都犯愁&#xff1a;到底哪個管用&#xff1f;我帶200多個小學生練過字&#xff0c;前前后后試了十款軟件&#xff0c;今天就掏心窩子說說——有的看著花哨其實沒用&#xff0c;有的專業是專業但…

第五天~提取Arxml的模板信息

?? ARXML模板信息提取:解鎖汽車軟件的樂高魔法 在汽車電子的世界里,AUTOSAR(汽車開放系統架構)如同無形的神經系統,而ARXML文件正是承載這套神經系統藍圖的數字載體。當工程師們需要批量創建或修改ECU(電子控制單元)配置時,模板信息提取便成為了一項至關重要的核心技…

react+antd+vite自動引入組件、圖標等

前言&#xff1a;react在使用antd的時候&#xff0c;也是需要每個組件都在界面上按需引入的&#xff0c;那能不能自動生成&#xff0c;按需使用呢&#xff1f;我們這里說一說這個。安裝插件&#xff0c;組件按需引入unplugin-antd-resolverunplugin-auto-importnpm install unp…

深度學習與遙感入門(六)|輕量化 MobileNetV2 高光譜分類

系列回顧&#xff1a; &#xff08;一&#xff09;CNN 基礎&#xff1a;高光譜圖像分類可視化全流程 &#xff08;二&#xff09;HybridNet&#xff08;CNNTransformer&#xff09;&#xff1a;提升全局感受野 &#xff08;三&#xff09;GCN 入門實戰&#xff1a;基于光譜 KNN…

第4節 神經網絡從公式簡化到卷積神經網絡(CNN)的進化之路

?? 深度學習的"玄學進化史" 從CNN用卷積層池化層處理圖片,循環網絡RNN如何利用上下文處理序列數據,到注意力機制讓Transformer橫空出世,現在的大語言模型已經能寫能畫能決策!每個新技巧都讓人驚呼"還能這么玩",難怪說深度學習像玄學——但這玄學,…

最新去水印小程序系統 前端+后端全套源碼 多套模版 免授權(源碼下載)

最新去水印小程序系統 前端后端全套源碼 多套模版 免授權 源碼下載&#xff1a;https://download.csdn.net/download/m0_66047725/91669468 更多資源下載&#xff1a;關注我

TCP Socket 編程實戰:實現簡易英譯漢服務

前言&#xff1a;TCP&#xff08;傳輸控制協議&#xff09;是一種面向連接、可靠的流式傳輸協議&#xff0c;與 UDP 的無連接特性不同&#xff0c;它通過三次握手建立連接、四次揮手斷開連接&#xff0c;提供數據確認、重傳機制&#xff0c;保證數據有序且完整傳輸。本文將基于…

CF566C Logistical Questions Solution

Description 給定一棵 nnn 個點的樹 TTT&#xff0c;點有點權 aia_iai?&#xff0c;邊有邊權 www. 定義 dist?(u,v)\operatorname{dist}(u,v)dist(u,v) 為 u→vu\to vu→v 的簡單路徑上的邊權和. 找到一個節點 uuu&#xff0c;使得 W∑i1ndist?(u,i)32aiW\sum\limits_{i1}^n…

聊天室全棧開發-保姆級教程(Node.js+Websocket+Redis+HTML+CSS)

前言 最近在學習websocket全雙工通信&#xff0c;想要做一個聯機小游戲&#xff0c;做游戲之前先做一個聊天室練練手。 跟著本篇博客&#xff0c;可以從0搭建一個屬于你自己的聊天室。 準備階段 什么人適合學習本篇文章&#xff1f; 答&#xff1a;前端開發者&#xff0c;有一…

后臺管理系統-2-vue3之路由配置和Main組件的初步搭建布局

文章目錄1 路由搭建1.1 路由創建(router/index.js)1.2 路由組件(views/Main.vue)1.3 路由引入并注冊(main.js)1.4 路由渲染(App.vue)2 element-plus的應用2.1 完整引入并注冊(main.js)2.2 示例應用(App.vue)3 ElementPlusIconsVue的應用3.1 圖標引入并注冊(main.js)3.2 示例應用…

使用 Let’s Encrypt 免費申請泛域名 SSL 證書,并實現自動續期

使用 Let’s Encrypt 免費申請泛域名 SSL 證書&#xff0c;并實現自動續期 目錄 使用 Let’s Encrypt 免費申請泛域名 SSL 證書&#xff0c;并實現自動續期 &#x1f6e0;? 環境準備&#x1f4a1; 什么是 Let’s Encrypt&#xff1f;&#x1f9e0; Let’s Encrypt 證書頒發原…

一鍵自動化:Kickstart無人值守安裝指南

Kickstart文件實現自動安裝1. Kickstart文件概述1.1 定義與作用Kickstart文件是Red Hat系Linux發行版&#xff08;如RHEL、CentOS、Fedora&#xff09;用于實現自動化安裝的配置文件&#xff0c;采用純文本格式保存。它通過預設安裝參數的方式&#xff0c;使系統安裝過程無需人…

深度解讀 Browser-Use:讓 AI 驅動瀏覽器自動化成為可能

目錄 一、什么是 Browser-Use&#xff1f; 二、Browser-Use 的核心功能 1. AI 與瀏覽器的鏈接橋梁 2. 無代碼 / 低代碼操作界面 3. 支持多家 LLM 4. 開發體驗簡潔 可快速上手 三、核心價值與適用場景 四、與 Playwright 的結合使用 五、總結與展望 https://github.com…

React.memo、useMemo 和 React.PureComponent的區別

useMemo 和 React.memo 都是 React 提供的性能優化工具&#xff0c;但它們的作用和使用場景有顯著不同。以下是兩者的全面對比&#xff1a; 一、核心區別總結特性useMemoReact.memo類型React Hook高階組件(HOC)作用對象緩存計算結果緩存組件渲染結果優化目標避免重復計算避免不…

Lumerical INTERCONNECT ------ CW Laser 和 OPWM 組成的系統

Lumerical INTERCONNECT ------ CW Laser 和 OPWM 組成的系統 引言 正文 引言 這里我們來簡單介紹一下 CW Laser 與 OSA 組成的簡單系統結構的仿真。 正文 我們構建一個如下圖所示的仿真結構。 我們將 CWL 中的 power 設置為 1 W。 然后直接運行仿真查看結果如下: 雖然 …

想漲薪30%?別只盯著大廠了!轉型AI產品經理的3個通用方法,人人都能學!

在AI產品經理剛成為互聯網公司香餑餑的時候&#xff0c;剛做產品1年的月月就規劃了自己的轉型計劃&#xff0c;然后用3個月時間成功更換賽道&#xff0c;轉戰AI產品經理&#xff0c;漲薪30%。 問及她有什么上岸秘訣&#xff1f;她也復盤總結了3個踩坑經驗和正確路徑&#xff0c…

基于Hadoop的全國農產品批發價格數據分析與可視化與價格預測研究

文章目錄有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主項目介紹每文一語有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主 項目介紹 隨著我國農業數字化進程的加快&#xff0c;農產品批發市場每天都會產生海量的價格…