当前位置: 首页 > article >正文

C#学习第15天:泛型

什么是泛型?


  • 定义:泛型允许您在类、接口和方法中定义占位符,这些占位符在使用时可以指定为具体的类型。
  • 作用:通过减少重复代码和提供更强的类型检查,提高了代码的可重用性和性能。

泛型的核心概念 


1.泛型类

  • 泛型类能够操作特定的数据类型,而不需要为每种数据类型写一个类。提高代码复用性。
using System;
using System.Collections.Generic;public class GenericContainer<T>
{private T item;// 设置泛型项的值public void SetItem(T value) {item = value;}// 获取泛型项的值public T GetItem(){return item;}
}

使用泛型类示例:

    public static void Demo(){// 使用int类型var intContainer = new GenericContainer<int>();intContainer.SetItem(10);// 使用string类型var stringContainer = new GenericContainer<string>();stringContainer.SetItem("Hello");}

2.泛型方法

可以在非泛型类中定义泛型方法,允许该方法独立于其所在类的参数类型。

public class GenericMethods
{// ref关键字表示参数按引用传递public void Swap<T>(ref T a, ref T b){T temp = a;a = b;b = temp;}// 演示多个类型参数的泛型方法public TResult Convert<TInput, TResult>(TInput input) where TResult : new(){// 处理类型转换逻辑return new TResult();}
}

使用泛型方法的示例:

    public static void Demo(){var methods = new GenericMethods();// 演示Swap方法int x = 10, y = 20;Console.WriteLine($"交换前: x = {x}, y = {y}");methods.Swap(ref x, ref y);Console.WriteLine($"交换后: x = {x}, y = {y}");string str1 = "Hello", str2 = "World";Console.WriteLine($"交换前: str1 = {str1}, str2 = {str2}");methods.Swap(ref str1, ref str2);Console.WriteLine($"交换后: str1 = {str1}, str2 = {str2}");// 演示Convert方法int number = 42;string result = methods.Convert<int, string>(number);Console.WriteLine($"转换结果: {result}");}

 3.泛型接口

允许接口的方法和属性使用泛型类型参数。

public interface IRepository<T>
{void Add(T item);void Remove(T item);T GetById(int id);IEnumerable<T> GetAll();
}

使用示例:

public class User
{public int Id { get; set; }public string Name { get; set; }
}// 实现用户仓储类
public class UserRepository : IRepository<User>
{private List<User> users = new List<User>();public void Add(User item){users.Add(item);}public void Remove(User item){users.Remove(item);}public User GetById(int id){return users.FirstOrDefault(u => u.Id == id);}public IEnumerable<User> GetAll(){return users;}
}// 演示仓储接口的使用
public static void Demo()
{var userRepo = new UserRepository();// 添加用户userRepo.Add(new User { Id = 1, Name = "张三" });userRepo.Add(new User { Id = 2, Name = "李四" });// 获取所有用户var allUsers = userRepo.GetAll();foreach (var user in allUsers){Console.WriteLine($"用户ID: {user.Id}, 名称: {user.Name}");}// 根据ID获取用户var user1 = userRepo.GetById(1);Console.WriteLine($"查找到用户: {user1?.Name}");// 删除用户userRepo.Remove(user1);
}

高级主题


约束

限制泛型参数的类型以增加灵活性和安全性。

  • where T : struct:T必须是值类型。
  • where T : class:T必须是引用类型。
  • where T : new():T必须有一个无参构造函数。
  • where T : BaseClass:T必须继承自BaseClass。
  • where T : InterfaceName:T必须实现某接口。
public class Example<T> where T : new()
{public T CreateInstance(){return new T();}
}public class GenericConstraints
{public T Sum<T>(T a, T b) where T : struct 
}

 泛型委托

泛型不仅适用于类和方法,还可以用于委托。

public delegate T Transformer<T>(T arg);class Program
{static int Square(int x) => x * x;static void Main(){Transformer<int> transformer = Square;Console.WriteLine(transformer(3)); // 输出:9}
}

使用场景


1.集合类

  • List<T>, Dictionary<TKey,TValue>, Queue<T>等都是泛型类的例子,可存储任何类型数据。

2.算法实现

  • 可以创建通用的排序、搜索或其他算法,适用于任何类型。

3.类型安全事件处理

  • 泛型委托用于事件系统中,确保类型匹配并提高安全性。

实践习题 


1.创建一个泛型栈类GenericStack<T>,实现基本的栈操作:Push、Pop和Peek。

using System;
using System.Collections.Generic;public class GenericStack<T>
{private List<T> elements = new List<T>();// 将元素添加到栈顶的Push操作public void Push(T item){elements.Add(item);}// 移除并返回栈顶元素的Pop操作public T Pop(){if (elements.Count == 0){throw new InvalidOperationException("The stack is empty.");}T item = elements[^1]; // ^1 是C# 8.0语法,用于访问最后一个元素elements.RemoveAt(elements.Count - 1);return item;}// 返回栈顶元素但不移除的Peek操作public T Peek(){if (elements.Count == 0){throw new InvalidOperationException("The stack is empty.");}return elements[^1];}
}public class Program
{public static void Main(){GenericStack<int> stack = new GenericStack<int>();stack.Push(10);stack.Push(20);stack.Push(30);Console.WriteLine(stack.Peek()); // 输出:30Console.WriteLine(stack.Pop());  // 输出:30Console.WriteLine(stack.Pop());  // 输出:20}
}

2.编写一个泛型类LimitedType<T>,仅允许实现了IDisposable接口的类型作为参数,并包含一个释放资源的方法。

using System;public class LimitedType<T> where T : IDisposable, new()
{private T resource;public LimitedType(){resource = new T();}public void UseResource(){Console.WriteLine($"Using resource of type {typeof(T).Name}");// 假装使用资源}public void ReleaseResource(){Console.WriteLine($"Releasing resource of type {typeof(T).Name}");resource.Dispose();}
}public class MyResource : IDisposable
{public void Dispose(){Console.WriteLine("MyResource disposed");}
}public class Program
{public static void Main(){LimitedType<MyResource> limitedResource = new LimitedType<MyResource>();limitedResource.UseResource();limitedResource.ReleaseResource();}
}

说明:

  • LimitedType类使用where T : IDisposable, new()约束,这意味着T必须实现IDisposable接口,并且具有无参构造函数。
  • UseResource模拟使用资源,而ReleaseResource负责正确地释放资源。
  • MyResource类实现了IDisposable接口,用于演示如何正确地处置资源。

通过这些例子,我们展示了如何利用泛型提高代码的通用性和灵活性。如果有任何问题或需要进一步讲解,请随时告诉我!
 

相关文章:

C#学习第15天:泛型

什么是泛型&#xff1f; 定义&#xff1a;泛型允许您在类、接口和方法中定义占位符&#xff0c;这些占位符在使用时可以指定为具体的类型。作用&#xff1a;通过减少重复代码和提供更强的类型检查&#xff0c;提高了代码的可重用性和性能。 泛型的核心概念 1.泛型类 泛型类能…...

WPF ObjectDataProvider

在 WPF(Windows Presentation Foundation)中,ObjectDataProvider 是一个非常有用的类,用于将非 UI 数据对象(如业务逻辑类或服务类)与 XAML 绑定集成。它允许在 XAML 中直接调用方法、访问属性或实例化对象,而无需编写额外的代码。以下是关于 ObjectDataProvider 的详细…...

Windows系统安装RustDesk Server的详细步骤和客户端设置

Windows系统安装RustDesk Server的详细步骤 在Windows系统上安装RustDesk Server涉及几个关键步骤,包括安装必要的依赖、下载RustDesk Server程序、配置并启动服务。以下是详细的步骤: 1. 安装Node.js和PM2 RustDesk Server的某些版本可能需要Node.js环境来运行,而PM2是一…...

RestSharp和Newtonsoft.Json结合发送和解析http

1.下载RestSharp和Newtonsoft.Json 2编写ApiRequest和ApiResponse和调用工具类HttpRestClient 请求模型 /// <summary>/// 请求模型/// </summary>public class ApiRequest{/// <summary>/// 请求地址/api路由地址/// </summary>public string Route {…...

《基于 RNN 的股票预测模型代码优化:从重塑到直接可视化》

在深度学习领域&#xff0c;使用循环神经网络&#xff08;RNN&#xff09;进行股票价格预测是一个常见且具有挑战性的任务。本文将围绕一段基于 RNN 的股票预测代码的改动前后差别展开&#xff0c;深入剖析代码的优化思路和效果。 原始代码思路与问题 原始代码实现了一个完整…...

【Pytorch之一】--torch.stack()方法详解

torch.stack方法详解 pytorch官网注释 Parameters tensors&#xff1a;张量序列&#xff0c;也就是要进行stack操作的对象们&#xff0c;可以有很多个张量。 dim&#xff1a;按照dim的方式对这些张量进行stack操作&#xff0c;也就是你要按照哪种堆叠方式对张量进行堆叠。dim的…...

半导体设备通信标准—secsgem v0.3.0版本使用说明文档(3)之SECS(SEMI E4,SEMI E5)

文章目录 1、变量1.1、数组类型1.2、获取数据1.3、设置数据1.4、编码/解码1.5、Array1.6、List1.7、动态变量 2、Items2.1、 Item types2.2、 Creating items2.1.1、 From value2.1.2、From SML text2.1.3、 From protocol text 2.3、 Getting data2.3.1、 Python value2.3.2、…...

数据中台(大数据平台)之数据资源目录

数据资源目录是数据管理的账本&#xff0c;是数据应用的基础&#xff0c;更是是数据治理成果的体现&#xff0c;因此数据中台产品应提供数据资源目录编制、发布、资源挂载、下架的管理能力。 1.数据资源目录分类 资源目录能够支持基于业务特点创建和维护基础目录分类和特色目…...

【随身WiFi】随身WiFi Debian系统优化教程

0.操作前必看 本教程基于Debian系统进行优化&#xff0c;有些操作对随身WiFi来说可能会带来负优化&#xff0c;根据需要选择。 所有操作需要在root用户环境下运行&#xff0c;否则都要加sudo 随身wifi Debian系统&#xff0c;可以去某安的随声WiFi模块自行搜索刷机 点赞&am…...

【WORD】批量将doc转为docx

具体步骤进行&#xff1a; 打开Word文档&#xff0c;按下AltF11快捷键&#xff0c;打开VBA编辑器。在VBA编辑器中&#xff0c;左侧的“项目资源管理器”窗口会显示当前打开的Word文档相关项目。找到您要添加代码的文档项目&#xff08;通常以文档名称命名&#xff09;&#xf…...

JAVA Web_定义Servlet2_学生登录验证Servlet

题目 页面StudentLogin.html中有一HTML的表单代码如下&#xff1a; <form action"studentLogin" method"post">学生姓名&#xff1a;<input type"text" name"stuName" value""><br>登录密码&#xff1a;…...

深入理解设计模式之模板方法模式 1d87ab8b42e98069b6c2c5a3d2710f9a

深入理解设计模式之模板方法模式 深入理解设计模式之模板方法模式 在软件开发的漫长征程中&#xff0c;我们常常会遇到各种复杂的业务逻辑&#xff0c;其中部分逻辑具有相似的流程框架&#xff0c;但在具体细节上又有所不同。这种情况下&#xff0c;模板方法模式就如同一位得…...

Unity入门笔记(缘更)

内容来源SiKi学院的Luna’s Fantasy 文章目录 一、基础知识1.准备2.基础知识1.层级(Layer)2.轴心点3.预制体(Prefab)4.刚体组件(Rigidbody)5.碰撞器组件(BoxCollider) 二、代码1.移动 一、基础知识 1.准备 Unity安装&#xff1a; https://unity.cn 2.基础知识 1.层级(Layer…...

【Python】用Python写一个俄罗斯方块玩玩

【Python】用Python写一个俄罗斯方块玩玩 一、引言1.成品效果展示 二、思考准备1.思考设计2.代码设计2.1 游戏页面2.2 控件设计2.2.1 方块生成2.2.2 方块碰撞2.2.3 方块消融2.2.4 游戏主循环2.2.5 游戏窗口 三、游戏完整版 一、引言 今日看到侄子在玩游戏&#xff0c;凑近一看…...

Java 本地缓存的实现:常见的四种方式

在 Java 中&#xff0c;常用的本地缓存实现主要有以下几种&#xff0c;以下是它们的代码示例及适用场景&#xff1a; 一、‌使用 ConcurrentHashMap 实现简单缓存‌ 适合轻量级、无需复杂淘汰策略的场景。 import java.util.concurrent.ConcurrentHashMap;public class Simp…...

记录一次生产中mysql主备延迟问题处理

登录库&#xff1a; mysql -uXXXX -pXXXX -P3306 -hXXXXXX -A 备库上执行&#xff1a;show slave status\G 查看 seconds_Behind_Master&#xff0c;延迟 2705s&#xff0c;而且还一直在增加。 SHOW CREATE TABLE proc_i_income_temp; -- 查看表的结构 show index from proc…...

路由器原理与配置技术详解

一、路由基础原理 1.1 路由器的核心功能 网络层设备&#xff1a;工作在OSI参考模型第三层&#xff0c;实现不同网络间的互联互通智能路径选择&#xff1a;基于路由表为数据包选择最优传输路径协议转换&#xff1a;处理不同网络接口间的协议差异&#xff08;如以太网与PPP&…...

第五节:React Hooks进阶篇-如何用useMemo/useCallback优化性能

反模式&#xff1a;滥用导致的内存开销React 19编译器自动Memoization原理 React Hooks 性能优化进阶&#xff1a;从手动到自动 Memoization &#xff08;基于 React 18 及以下版本&#xff0c;结合 React 19 新特性分析&#xff09; 一、useMemo/useCallback 的正确使用场景…...

STL迭代器:C++泛型编程的核心工具 [特殊字符]

在C中&#xff0c;STL&#xff08;标准模板库&#xff09;的迭代器是泛型编程的核心&#xff0c;它不仅解决了指针的局限性&#xff0c;还为算法与容器之间提供了抽象的访问接口。接下来&#xff0c;我们将探讨迭代器的核心作用、与指针的关键区别以及其设计哲学。 一、迭代器的…...

ffmpeg无损转格式的命令行

将ffmpeg.exe拖入命令行窗口 c:\users\zhangsan>D:\ffmpeg-2025-03-11\bin\ffmpeg.exe -i happy.mp4 -c:v copy -c:a copy 格式转换后.mkv -c:v copy 仅做拷贝视频,不重新编码 -c:a copy 仅做拷贝音频 ,不重新编码...

Monorepo 是什么?前端项目的多模块管理终极方案

前言 你是否曾经维护过多个前端项目?是否在多个项目之间来回复制粘贴组件,工具函数?是否经常被"组件更新没同步","构建时间太长","依赖版本冲突"等问题困扰? 这些问题都指向一个关键点: 项目结构和管理方式 今天,我来聊聊一种非常火但又容…...

对象池模式在uniapp鸿蒙APP中的深度应用

文章目录 对象池模式在uniapp鸿蒙APP中的深度应用指南一、对象池模式核心概念1.1 什么是对象池模式&#xff1f;1.2 为什么在鸿蒙APP中需要对象池&#xff1f;1.3 性能对比数据 二、uniapp中的对象池完整实现2.1 基础对象池实现2.1.1 核心代码结构2.1.2 在Vue组件中的应用 2.2 …...

条款05:了解C++默默编写并调用哪些函数

目录 1.默认生成的函数 2.无法生成的情况 2.1当成员函数有引用 或者 被const修饰 2.2.operator在基类被私有 1.默认生成的函数 class empty {};//相当于class empty { public:empty(){ ... } // 构造函数empty(const empty& rhs) { ... }// 拷贝构造~empty(){ ... } //…...

PythonFlask打造高效流式接口的实战

一、环境搭建与项目初始化 要使用 Flask 提供流式接口,首先得确保开发环境正确配置。在 Ubuntu 系统上,可借助 apt 包管理器便捷安装 Python 和 pip: sudo apt update sudo apt install python3 python3-pip对于 Windows 用户,推荐从官网下载安装包进行安装。安装完成后,…...

强化学习算法系列(五):最主流的算法框架——Actor-Critic算法框架

强化学习算法 &#xff08;一&#xff09;动态规划方法——策略迭代算法(PI)和值迭代算法(VI) &#xff08;二&#xff09;Model-Free类方法——蒙特卡洛算法(MC)和时序差分算法(TD) &#xff08;三&#xff09;基于动作值的算法——Sarsa算法与Q-Learning算法 &#xff08;四…...

设计模式(结构型)-桥接模式

目录 摘要 定义 类图 角色 具体实现 优缺点 优点 缺点 使用场景 使用案例 JDBC 和桥接模式 总结 摘要 在软件开发领域&#xff0c;随着系统规模和复杂性的不断攀升&#xff0c;如何设计出具有良好扩展性、灵活性以及可维护性的软件架构成为关键挑战。桥接模式作为一…...

【MySQL】MySQL数据库 —— 简单认识

目录 1. 数据库的介绍 1.1 什么是数据库 1.2 数据库和数据结构之间关系 2. 数据库分类 2.1 关系型数据库&#xff08;RDBMS&#xff09; 2.2 非关系型数据库 2.3 区别 一些行内名词简单解释&#xff1a; 3. 关于mysql 主要学什么 4. MySQL中重要的概念 4.1 概念 4…...

RNN - 语言模型

语言模型 给定文本序列 x 1 , … , x T x_1, \ldots, x_T x1​,…,xT​&#xff0c;语言模型的目标是估计联合概率 p ( x 1 , … , x T ) p(x_1, \ldots, x_T) p(x1​,…,xT​)它的应用包括 做预训练模型&#xff08;eg BERT&#xff0c;GPT-3&#xff09;生成本文&#xff…...

过拟合、归一化、正则化、鞍点

过拟合 过拟合的本质原因往往是因为模型具备方差很大的权重参数。 定义一个有4个特征的输入&#xff0c;特征向量为,定义一个模型&#xff0c;其只有4个参数&#xff0c;表示为。当模型过拟合时&#xff0c;这四个权重参数的方差会很大&#xff0c;可以假设为。当经过这个模型后…...

【python画图】:从入门到精通绘制完美柱状图

目录 Python数据可视化&#xff1a;从入门到精通绘制完美柱状图一、基础篇&#xff1a;快速绘制柱状图1.1 使用Matplotlib基础绘制1.2 使用Pandas快速绘图 二、进阶篇&#xff1a;专业级柱状图定制2.1 多系列柱状图2.2 堆叠柱状图2.3 水平柱状图 三、专业参数速查表Matplotlib …...