C#中泛型的应用说明

server/2024/10/19 11:04:11/

一、泛型概述

泛型的主要目的是提高代码的复用性和类型安全性,通过使用泛型,可以创建处理任何数据类型的类和方法,而无需为每种数据类型都编写一个单独的类或方法。同时,泛型还可以在编译时提供类型检查,从而避免在运行时出现类型错误。

二、泛型定义

在C#中,我们可以通过在类、接口、方法或委托的名称后面添加尖括号<>来定义泛型。尖括号中包含的类型参数可以是任何有效的C#类型,包括类、结构、接口、委托等。

2.1 泛型方法的声明

   //实现string 转换为其他类型
        public static T TypeConvert<T>(string val)  
        {
            //代码首先检查传入的字符串val是否为空、空白或为null。如果是,则直接返回该类型的默认值(例如,对于引用类型,返回null;对于值类型,返回其默认值,如0或false)。
            if (String.IsNullOrWhiteSpace(val))
                return default(T);
            //如果T是一个枚举类型,则使用Enum.Parse方法将字符串val解析为该枚举类型的值。true参数表示不区分大小写。
            if (typeof(T).IsEnum)
                return (T)Enum.Parse(typeof(T), val, true);
            //如果T不是枚举类型,则使用Convert.ChangeType方法将字符串val转换为T类型。如果转换失败,会抛出异常。
            return (T)Convert.ChangeType(val, typeof(T));
        }

2.1.1.用途

这个方法的主要用途是提供一个通用的字符串到类型的转换功能,适用于各种不同的类型,包括但不限于基本数据类型、枚举类型和自定义类型。它简化了类型转换的代码,使得代码更加简洁和易于维护。

2.2.2.注意事项

a.异常处理:如果Convert.ChangeType方法无法将字符串转换为指定的类型,会抛出InvalidCastException异常。在实际使用中,可能需要添加异常处理代码来捕获并处理这种异常;

b.枚举类型转换Enum.Parse方法在解析枚举值时,如果字符串val不匹配任何枚举成员,会抛出ArgumentException异常。因此,使用此方法时也需要考虑异常处理;

c.性能考虑:对于大量数据的转换,频繁调用此方法可能会影响性能。如果性能是一个关键考虑因素,可能需要寻找更高效的转换方法;

d.类型安全性:使用泛型方法时,编译器无法在编译时检查类型转换的正确性,因此需要在运行时处理可能的异常。

2.2 泛型方法的调用 

 int num = TypeConvert<int>("1");//将字符l类型的1转换成int 类型的数字1

 三、泛型类和泛型接口

3.1 泛型类的声明

泛型类就是一个类可以实现多个类型的需求,常用的集合List<T> 就是一个泛型类,可以转到定义看到其声明 public class List<T> ,当然进行实例化的时候,必须要指定类型,List<string> names = new List<string>(); 

3.2 泛型接口

泛型接口,就是一个接口 满足多个多个类型的需求。

//声明泛型接口 public interface GenericInterface<T>
{

四、泛型委托

泛型委托与普通的委托相比,它可以适应更多的类型,一般提供了两种泛型委托,一个是Action,无返回值,另一个是Func,带返回值。通常可以自定义泛型委托,如下所示:

public delegate void GenericDelegate <T>(T para);

五、泛型约束

虽然泛型允许我们使用任何类型作为类型参数,但有时候可能需要对类型参数进行一些限制。这时,可以使用泛型约束来实现。泛型约束可以在类、接口或方法的定义中指定,以限制类型参数的类型范围。

C#提供了多种泛型约束,包括:

  • where T : struct:约束类型参数必须是值类型。这确保了类型参数是如intdoublestruct等值类型,而不是引用类型。
  • where T : class:约束类型参数必须是引用类型。这允许你指定类型参数必须是类、接口、委托或数组等引用类型。
  • where T : new():约束类型参数必须有一个无参数的构造函数。这确保了你可以创建该类型的新实例,这在某些需要实例化对象的泛型方法或类中特别有用。
  • where T : BaseClass:约束类型参数必须是BaseClass或其派生类。这允许你指定类型参数必须是某个特定类的子类或该类本身,从而确保类型参数具有某些特定的方法或属性。
  • where T : IInterface:约束类型参数必须实现IInterface接口。这确保了类型参数具有接口中定义的所有方法和属性,这对于确保类型参数符合某种约定或标准非常有用。

在使用泛型约束时,可以在一个泛型定义中指定多个约束。例如,可以同时要求一个类型参数是某个类的子类,并且实现某个接口。但是,这些约束之间必须是逻辑上兼容的,否则编译器会报错。下面是一个使用泛型约束的示例:

        public class GenericList<T> where T : class, IComparable<T>{private List<T> items = new List<T>();//创建一个泛型列表来存储元素public void Add(T item)//添加元素的方法{items.Add(item);}public T GetMax()//获取最大值的方法{if (items.Count == 0)throw new InvalidOperationException("List is empty.");T max = items[0];foreach (T item in items){if (item.CompareTo(max) > 0)max = item;}return max;}}

 在这个示例中,定义了一个泛型类GenericList<T>,它接受一个类型参数T。使用where子句来约束T,要求它必须是引用类型(class),并且必须实现IComparable<T>接口。这样,就可以在GetMax方法中使用CompareTo方法来比较列表中的元素,从而找出最大值。如果类型参数不满足这些约束,编译器将报错。

六、泛型的优点

使用泛型可以带来以下优点:

  • 代码复用:通过定义泛型,我们可以编写一次代码,然后将其用于处理任何类型的数据,从而减少了重复代码的编写。
  • 类型安全:泛型可以在编译时进行类型检查,从而避免了在运行时出现类型错误。
  • 性能:由于泛型在编译时会将类型参数替换为具体的类型,因此可以避免在运行时进行类型检查和装箱/拆箱操作,从而提高了性能。

七、泛型的限制和注意事项

虽然泛型带来了许多优点,但在使用时也需要注意一些限制和注意事项。如,泛型不能用于静态字段或属性,因为静态成员是与类型本身关联的,而不是与类型参数关联的。此外,泛型也不能用于值类型的数组创建,因为值类型在编译时需要确定其大小。另外,虽然泛型可以提高类型安全性,但在某些情况下可能会增加代码的复杂性。因此,在使用泛型时需要根据具体的需求和场景进行权衡和选择。


http://www.ppmy.cn/server/131122.html

相关文章

SeleniumBase在无头模式下绕过验证码的完整指南

概述 在现代Web爬虫技术中&#xff0c;SeleniumBase 是一款强大的自动化测试工具&#xff0c;能够模拟用户行为&#xff0c;进行高效的数据采集。然而&#xff0c;验证码&#xff08;CAPTCHA&#xff09;常常成为爬虫项目中的一个难题&#xff0c;尤其是在无头模式&#xff08…

HarmonyOS NEXT 应用开发实战(三、ArkUI页面底部导航TabBar的实现)

在开发HarmonyOS NEXT应用时&#xff0c;TabBar是用户界面设计中不可或缺的一部分。本文将通过代码示例&#xff0c;带领大家一同实现一个常用的TabBar&#xff0c;涵盖三个主要的内容页&#xff1a;首页、知乎日报和我的页面。以模仿知乎日报的项目为背景驱动&#xff0c;设定…

《机器学习与数据挖掘综合实践》实训课程教学解决方案

一、引言 随着信息技术的飞速发展&#xff0c;人工智能已成为推动社会进步的重要力量。作为人工智能的核心技术之一&#xff0c;机器学习与数据挖掘在各行各业的应用日益广泛。本方案旨在通过系统的理论教学、丰富的实践案例和先进的实训平台&#xff0c;帮助学生掌握机器学习…

Go 语言中的格式化占位符

在 Go 语言中&#xff0c;fmt 包提供了大量的格式化占位符&#xff0c;用于格式化输出不同类型的数据。选择合适的占位符&#xff0c;可以确保输出的内容格式正确、清晰易懂。 常见的占位符&#xff1a; 基本类型 %v&#xff1a;按值的默认格式输出。适用于任何类型。%v&…

【千库网-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

机器学习笔记(四)-决策树

决策过程的最终结果对应我们期望的判定结果&#xff0c;一颗决策树包含一个根结点、若干个内部结点、若干个叶结点。决策树的生成是一个递归的过程&#xff0c;一般三种情况会导致递归返回&#xff1a; &#xff08;1&#xff09;当前结点包含的样本属于同一类别&#xff0c;无…

小米电机与STM32——CAN通信

背景介绍&#xff1a;为了利用小米电机&#xff0c;搭建机械臂的关节&#xff0c;需要学习小米电机的使用方法。计划采用STM32驱动小米电机&#xff0c;实现指定运动&#xff0c;为此需要了解他们之间的通信方式&#xff0c;指令写入方法等。花了很多时间学习&#xff0c;但网络…

react+ts+vite 别名一直爆红问题

已经配置如下代码安装了types/node import path from "path"; // https://vitejs.dev/config/ export default defineConfig({plugins: [react()],server: {proxy: {"/api": {target: "http://localhost:3000",changeOrigin: true,rewrite: (pa…