C# 泛型

泛型

泛型不是语法糖,而是由框架提供的一种便捷语法,首次出现在.NET 2.0中。

1. 泛型定义

  • 泛型:是一种程序特性,定义时不对类型做出明确的规定,使用时规定且不能改变。
  • 一般应用:泛型集合、泛型方法、泛型类、泛型委托。
    • 泛型方法:方法的返回值类型、参数类型定义成泛型类型。
    • 泛型集合:如List<T>Dictionary<K, V>,所在命名空间:System.Collections.Generic
    • 非泛型集合:ArrayListHashtable,所在命名空间:System.Collections。非泛型集合中可以添加任意类型,但对于数据本身来说,这是非常不安全的,并且存在装箱和拆箱问题。
      • 装箱:将值类型的元素放到集合中会被转换成object类型。
      • 拆箱:将一个集合的元素取出来,但这个元素本身是值类型,必须进行强制类型转换。
      • 弊端:如果存储大量的数据,会影响性能。

2. 泛型赋值与约束

  • default关键字:主要用于直接的赋值,引用类型赋值为null,值类型给值默认值,如T a = default(T)
  • 泛型约束
    • where T1 : class // T1必须是引用类型。
    • where T2 : struct // T2必须是值类型。
    • where T3 : new() // 必须有一个无参构造方法。
    • where T4 : 接口 // 接口约束。
    • where T5 : 类名 // 基类约束。
  • 约束是可以叠加的,比单个基类更灵活的约束目标。
  • 由于泛型类型是不确定的,所以泛型类型在编译阶段无法直接转换。可采用dynamic类,在运行动态解析对象类型。在编译阶段是不解析的,类型转换不对,会在运行时报错。

代码示例

1. 代码重用
public class GenericList<T>
{private T[] items;private int count;public GenericList(int capacity){items = new T[capacity];}public void Add(T item){if (count == items.Length){throw new IndexOutOfRangeException("List is full");}items[count] = item;count++;}// 其他方法...
}// 使用示例
var intList = new GenericList<int>(10);
intList.Add(1);
intList.Add(2);var stringList = new GenericList<string>(5);
stringList.Add("Hello");
stringList.Add("World");
2. 类型安全
// 使用泛型集合,无需担心类型错误
List<int> intList = new List<int>();
intList.Add(1);
// intList.Add("string"); // 编译错误,因为集合是 int 类型的
3. 性能优化
// 使用泛型集合避免了装箱和拆箱操作
List<int> intList = new List<int>();
intList.Add(1);
int firstInt = intList[0]; // 直接访问,无需拆箱// 相比之下,使用非泛型集合会有装箱和拆箱开销
ArrayList arrayList = new ArrayList();
arrayList.Add(1); // 装箱
int firstValue = (int)arrayList[0]; // 拆箱
4. 减少代码冗余
// 泛型类可以替代多个具有相似功能的类
Stack<int> intStack = new Stack<int>();
intStack.Push(1);
int topInt = intStack.Pop();Stack<string> stringStack = new Stack<string>();
stringStack.Push("Hello");
string topString = stringStack.Pop();
5. 扩展性
public interface IRepository<T>
{T Get(int id);void Add(T item);// 其他方法...
}public class ProductRepository : IRepository<Product>
{// 实现 IRepository<Product> 接口的方法
}IRepository<Product> productRepo = new ProductRepository();
Product product = productRepo.Get(1);
6. 泛型约束示例
public class GenericComparer<T> where T : IComparable<T>
{public int Compare(T x, T y){return x.CompareTo(y);}
}var comparer = new GenericComparer<int>();
int result = comparer.Compare(1, 2); // 返回 -1
7. 与集合框架的集成
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
Dictionary<string, int> ages = new Dictionary<string, int>();
ages.Add("Alice", 30);
ages.Add("Bob", 25);var olderThan30 = ages.Where(entry => entry.Value > 30);
foreach (var pair in olderThan30)
{Console.WriteLine("{0} is {1} years old.", pair.Key, pair.Value);
}
8. 泛型委托示例
public delegate TResult GenericDelegate<T, TResult>(T arg);public class GenericClass
{public static int Double(int value){return value * 2;}
}GenericDelegate<int, int> del = GenericClass.Double;
int result = del(5); // 结果为 10

高级用法与技巧

泛型在反射中的应用
创建泛型类型的实例
using System;
using System.Reflection;public class GenericClass<T>
{public T Property { get; set; }public GenericClass(T property){Property = property;}
}class Program
{static void Main(){Type genericType = typeof(GenericClass<>);Type specificType = genericType.MakeGenericType(typeof(int));object instance = Activator.CreateInstance(specificType, 42);Console.WriteLine(((GenericClass<int>)instance).Property); // 输出: 42}
}
调用泛型方法
using System;
using System.Reflection;public class GenericMethodsClass
{public void GenericMethod<T>(T param){Console.WriteLine(param);}
}class Program
{static void Main(){var genericMethodsClass = new GenericMethodsClass();MethodInfo genericMethod = typeof(GenericMethodsClass).GetMethod("GenericMethod");MethodInfo specificMethod = genericMethod.MakeGenericMethod(typeof(string));specificMethod.Invoke(genericMethodsClass, new object[] { "Hello, World!" }); // 输出: Hello, World!}
}
协变和逆变
协变(Covariance)
using System;
using System.Collections.Generic;public class CovarianceExample
{public static void PrintValues<T>(IEnumerable<T> collection){foreach (var item in collection){Console.WriteLine(item);}}static void Main(){IEnumerable<string> strings = new List<string> { "A", "B", "C" };// 协变使得可以将IEnumerable<string>赋值给IEnumerable<object>IEnumerable<object> objects = strings;PrintValues(objects); // 输出: A, B, C}
}
逆变(Contravariance)
using System;
using System.Collections.Generic;public class ContravarianceExample
{public static void Compare<T>(T first, T second, IComparer<T> comparer){if (comparer.Compare(first, second) > 0){Console.WriteLine($"{first} is greater than {second}.");}else{Console.WriteLine($"{first} is less than or equal to {second}.");}}static void Main(){// 逆变使得可以将IComparer<object>赋值给IComparer<string>IComparer<object> objectComparer = Comparer<object>.Default;IComparer<string> stringComparer = objectComparer;Compare("apple", "orange", stringComparer); // 输出可能因默认比较器而异}
}

在这两个例子中,协变允许我们将一个更具体的集合类型(如IEnumerable<string>)赋值给一个较不具体的类型(如IEnumerable<object>)。而逆变则允许我们将一个较不具体的比较器类型(如IComparer<object>)赋值给一个更具体的类型(如IComparer<string>)。这两个特性在泛型编程中非常有用,因为它们提供了更大的灵活性和类型安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/43395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习——LR、‌GBDT、‌SVM、‌CNN、‌DNN、‌RNN、‌Word2Vec等模型的原理和应用

LR&#xff08;逻辑回归&#xff09; 原理&#xff1a; 逻辑回归模型&#xff08;Logistic Regression, LR&#xff09;是一种广泛应用于分类问题的统计方法&#xff0c;尤其适用于二分类问题。其核心思想是通过Sigmoid函数将线性回归模型的输出映射到(0,1)区间&#xff0c;从…

【AI前沿】深度学习:神经网络基础

文章目录 &#x1f4d1;引言一、神经元和感知器1.1 神经元的基本概念1.2 感知器模型 二、多层感知器&#xff08;MLP&#xff09;2.1 MLP的基本结构2.2 激活函数的重要性2.3 激活函数2.4 激活函数的选择 三、小结 &#x1f4d1;引言 深度学习是现代人工智能的核心技术之一&…

kotlin Flow 学习指南 (三)最终篇

目录 前言Flow生命周期StateFlow 替代LiveDataSharedFlow其他常见应用场景处理复杂、耗时逻辑存在依赖关系的接口请求组合多个接口的数据 Flow使用注意事项总结 前言 前面两篇文章&#xff0c;介绍了Flow是什么&#xff0c;如何使用&#xff0c;以及相关的操作符进阶&#xff…

如何挑选适合的需求池管理系统?10款优质工具分享

本文将分享10款优质需求池管理工具&#xff1a;PingCode、Worktile、Teambition、Epicor Kinetic、TAPD、SAP IBP、Logility、RELEX Solutions、JIRA、明道云。 在管理项目和产品需求时&#xff0c;正确的工具能够大幅提高效率与透明度。如何从众多需求池工具中选择最适合团队的…

第一节 SHELL脚本中的常用命令(2)

二,网络管理命令nmcli 1.查看网卡 # 或者先用ip addr或ip a等查看网卡 ip a s 网卡名 ifconfig 网卡名 nmcil device show 网卡名 nmcil device status nmcil connection show 网卡名2.设置网卡 a)当网卡未被设置过时 设置dncp网络工作模式 nmcil connection add con-name…

Rust编程-编写自动化测试

编写单元测试步骤&#xff1a; 1. 准备所需的数据 2. 调用需要测试的代码 3. 断言运行结果与我们所期望的一致 Rust的test元数据&#xff1a; #[cfg(test)]&#xff1a;是一个属性宏&#xff08;attribute macro&#xff09;。用于控制特定的代码段仅在测试环境中编译…

自定义类型:联合体

像结构体一样&#xff0c;联合体也是由一个或者多个成员组成&#xff0c;这些成员可以是不同的类型。 联合体类型的声明 编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫&#xff1a;共⽤体。 输出结果&#xff1a; 联合体…

size_t 数据类型的好处

什么是size_t size_t 类型在不同的平台上对应不同的底层整数类型&#xff0c;具体取决于平台的指针大小。size_t 主要用于表示大小和长度&#xff0c;如数组的元素数量、缓冲区的大小等&#xff0c;它的设计目的是为了匹配指针的大小&#xff0c;以避免类型不匹配引起的错误。…

代码随想录算法训练营DAY58|101.孤岛的总面积、102.沉没孤岛、103. 水流问题、104.建造最大岛屿

忙。。。写了好久。。。。慢慢补吧。 101.孤岛的总面积 先把周边的岛屿变成水dfs def dfs(x, y, graph, s):if x<0 or x>len(graph) or y<0 or y>len(graph[0]) or graph[x][y]0:return sgraph[x][y]0s1s dfs(x1, y, graph, s)s dfs(x-1, y, graph, s)s dfs(…

【爬虫入门知识讲解:xpath】

3.3、xpath xpath在Python的爬虫学习中&#xff0c;起着举足轻重的地位&#xff0c;对比正则表达式 re两者可以完成同样的工作&#xff0c;实现的功能也差不多&#xff0c;但xpath明显比re具有优势&#xff0c;在网页分析上使re退居二线。 xpath 全称为XML Path Language 一种…

软考高级第四版备考--第16天(规划沟通管理)Plan Communication Management

定义&#xff1a;基于每个干系人或干系人群体的信息需求、可用的组织资产以及具体的项目的需求&#xff0c;为项目沟通活动制定恰当的方法和计划的过程。 作用&#xff1a; 及时向干系人提供相关信息&#xff1b;引导干系人有效参与项目&#xff1b;编制书面沟通计划&#xf…

【基于R语言群体遗传学】-16-中性检验Tajima‘s D及连锁不平衡 linkage disequilibrium (LD)

Tajimas D Test 已经开发了几种中性检验&#xff0c;用于识别模型假设的潜在偏差。在这里&#xff0c;我们将说明一种有影响力的中性检验&#xff0c;即Tajimas D&#xff08;Tajima 1989&#xff09;。Tajimas D通过比较数据集中的两个&#x1d703; 4N&#x1d707;估计值来…

vue项目中常见的一些preset及其关系

Babel的作用 Babel主要用途是用来做js代码转换的&#xff0c;将最新的js语法或者api转换成低版本浏览器可兼容执行的代码。 语法兼容是指一些浏览器新特性增加的js写法&#xff0c;例如箭头函数 ()>{}&#xff1b;低版本的浏览器无法识别这些&#xff0c;会导致一些语法解…

spark shuffle写操作——UnsafeShuffleWriter

PackedRecordPointer 使用long类型packedRecordPointer存储数据。 数据结构为&#xff1a;[24 bit partition number][13 bit memory page number][27 bit offset in page] LongArray LongArray不同于java中long数组。LongArray可以使用堆内内存也可以使用堆外内存。 Memor…

秋招突击——7/9——字节面经

文章目录 引言正文八股MySQL熟悉吗&#xff1f;讲一下MySQL索引的结构&#xff1f;追问&#xff1a;MySQL为什么要使用B树&#xff1f;在使用MySQL的时候&#xff0c;如何避免索引失效&#xff1f;讲一下MySQL的事物有哪几种特征&#xff1f;MySQL的原子性可以实现什么效果&…

GESP C++ 三级真题(2023年9月)T2 进制判断

进制判断 问题描述 N进制数指的是逢N进一的计数制。例如&#xff0c;人们日常生活中大多使用十进制计数&#xff0c; 而计算机底层则一般使用二进制。除此之外&#xff0c;八进制和十六进制在一些场合也是 常用的计数制(十六进制中&#xff0c;一般使用字母A至F表示十至十五…

【区块链+跨境服务】粤澳健康码跨境互认系统 | FISCO BCOS应用案例

2020 年突如其来的新冠肺炎疫情&#xff0c;让社会治理体系面临前所未见的考验&#xff0c;如何兼顾疫情防控与复工复产成为社会 各界共同努力的目标。区块链技术作为传递信任的新一代信息基础设施&#xff0c;善于在多方协同的场景中发挥所长&#xff0c;从 而为粤澳两地的疫情…

uniapp上传文件并获取上传进度

1. 上传普通文件 uni.chooseMessageFile({count: 1,success: (res) > {console.log(res)console.log("res123456", res.tempFiles[0].path)const uploadTask uni.uploadFile({url: http://localhost:8000/demo,filePath: res.tempFiles[0].path,name: file,form…

CSS关于居中的问题

文章目录 1. 行内和块级元素自身相对父控件居中1.1. 块级元素相对父控件居中1.2. 行内元素相对于父控件居中 2. 实现单行文字垂直居中3. 子绝父相实现子元素的水平垂直居中3.1. 方案一3.1.1. 示例 3.2. 方案二3.2.1. 示例 3.3. 方案三(推荐)3.3.1. 示例 3.4. 方案四(了解一下) …

AI大模型知识点大梳理_ai大模型的精度以下哪项描述的准确

AI大模型是什么 AI大模型是指具有巨大参数量的深度学习模型&#xff0c;通常**包含数十亿甚至数万亿个参数。**这些模型可以通过学习大量的数据来提高预测能力&#xff0c;从而在自然语言处理、计算机视觉、自主驾驶等领域取得重要突破。 AI大模型的定义具体可以根据参数规模…