C# 泛型介绍
C# 中的泛型(Generics)是一种强类型参数化的特性,它允许你编写不具体指定数据类型的代码,而在实际使用时再指定具体的类型。泛型的引入使得代码更加灵活、可重用,并提高了类型安全性。
C#泛型基本用法
以下是一个简单的 C# 泛型代码示例,展示了如何定义泛型类和泛型方法,以及如何使用泛型来创建通用的数据结构。
using System;
using System.Collections.Generic;// 泛型类示例
public class GenericClass<T>
{private T genericField;public GenericClass(T value){this.genericField = value;}public T GetValue(){return genericField;}
}// 泛型方法示例
public class GenericMethod
{public T GenericMethodExample<T>(T value){Console.WriteLine($"Received value of type {typeof(T)}: {value}");return value;}
}// 泛型接口示例
public interface IGenericInterface<T>
{void PrintValue(T value);
}// 泛型集合示例
public class GenericCollectionExample
{public void ShowGenericList(){List<int> intList = new List<int> { 1, 2, 3, 4, 5 };List<string> stringList = new List<string> { "apple", "orange", "banana" };PrintList(intList);PrintList(stringList);}private void PrintList<T>(List<T> list){foreach (var item in list){Console.WriteLine(item);}}
}class Program
{static void Main(){// 使用泛型类GenericClass<int> intGenericClass = new GenericClass<int>(42);int intValue = intGenericClass.GetValue();Console.WriteLine($"GenericClass<int> value: {intValue}");GenericClass<string> stringGenericClass = new GenericClass<string>("Hello, Generics!");string stringValue = stringGenericClass.GetValue();Console.WriteLine($"GenericClass<string> value: {stringValue}");// 使用泛型方法GenericMethod genericMethod = new GenericMethod();genericMethod.GenericMethodExample(123);genericMethod.GenericMethodExample("Generic Method");// 使用泛型接口GenericInterfaceImplementation<int> genericInterfaceImpl = new GenericInterfaceImplementation<int>();genericInterfaceImpl.PrintValue(123);// 使用泛型集合GenericCollectionExample collectionExample = new GenericCollectionExample();collectionExample.ShowGenericList();}
}// 实现泛型接口
public class GenericInterfaceImplementation<T> : IGenericInterface<T>
{public void PrintValue(T value){Console.WriteLine($"Received value of type {typeof(T)}: {value}");}
}
在上面的示例中,GenericClass
是一个泛型类,可以用不同的类型实例化。GenericMethod
是一个包含泛型方法的类,可以在调用时指定不同的类型。IGenericInterface
是一个泛型接口,它定义了一个方法,实现类 GenericInterfaceImplementation
实现了这个接口并指定了具体的类型。GenericCollectionExample
展示了如何使用泛型集合(这里使用了 List<T>
)。
通过使用泛型,你可以写出更加通用、灵活、类型安全的代码,同时减少了代码的冗余。
泛型方法详细介绍
在C#中,泛型方法是一种允许你在方法中使用一个或多个类型参数的方法。泛型方法可以在类、结构体、接口和委托中定义,并且能够提供更灵活、通用的代码,同时保持类型安全。
以下是一个简单的泛型方法的示例:
public class GenericMethodExample
{// 泛型方法示例public T GenericMethod<T>(T value){Console.WriteLine($"Received value of type {typeof(T)}: {value}");return value;}
}class Program
{static void Main(){GenericMethodExample example = new GenericMethodExample();// 调用泛型方法时可以显式指定类型参数int intValue = example.GenericMethod<int>(42);// 编译器可以自动推断类型参数string stringValue = example.GenericMethod("Hello, Generics!");// 泛型方法可以处理不同类型的参数double doubleValue = example.GenericMethod(3.14);// 泛型方法也可以用于引用类型List<int> intList = new List<int> { 1, 2, 3 };example.GenericMethod(intList);}
}
在这个例子中,GenericMethod
是一个泛型方法,它使用了类型参数 T
。当调用这个方法时,可以显式指定类型参数,也可以让编译器根据参数类型自动推断类型参数。这使得这个方法可以用于处理不同类型的数据,而无需为每个数据类型都编写一个单独的方法。
泛型方法的优势在于它们提供了一种更灵活、通用的方式来处理数据,同时保持了类型安全。泛型方法在集合操作、算法实现以及其他需要通用性的场景中特别有用。
泛型其它用法
除了基本的泛型类、泛型方法和泛型接口之外,C# 还提供了一些更高级的泛型用法,包括泛型约束、泛型委托、协变和逆变等。下面是一些高级的泛型用法示例:
泛型约束(Generic Constraints):
泛型约束用于限制泛型类型参数的类型。常见的约束有 where T : 类型
,它表示 T 必须是指定类型或其派生类。以下是一个示例:
public class GenericConstraintExample<T> where T : class
{public void PrintTypeName(T value){Console.WriteLine($"Type of the value: {typeof(T)}");}
}
在这个例子中,where T : class
表示泛型类型参数 T
必须是引用类型。
泛型委托(Generic Delegates):
你可以使用泛型委托来创建通用的委托,使其能够处理不同类型的方法。以下是一个使用泛型委托的示例:
public delegate void GenericDelegate<T>(T value);public class GenericDelegateExample
{public void PrintInt(int x){Console.WriteLine($"PrintInt: {x}");}public void PrintString(string s){Console.WriteLine($"PrintString: {s}");}
}class Program
{static void Main(){GenericDelegateExample example = new GenericDelegateExample();GenericDelegate<int> intDelegate = example.PrintInt;GenericDelegate<string> stringDelegate = example.PrintString;intDelegate(42);stringDelegate("Hello, Generics!");}
}
协变和逆变(Covariance and Contravariance):
协变和逆变是与泛型接口和委托一起使用的高级概念,允许你使用派生类型替代基类型(协变)或使用基类型替代派生类型(逆变)。以下是一个协变的示例:
public interface IMyInterface<out T>
{T GetItem();
}public class MyImplementation<T> : IMyInterface<T>
{private T item;public MyImplementation(T item){this.item = item;}public T GetItem(){return item;}
}class Program
{static void Main(){IMyInterface<string> stringInterface = new MyImplementation<string>("Hello, Covariance!");IMyInterface<object> objectInterface = stringInterface;Console.WriteLine(objectInterface.GetItem()); // 输出: Hello, Covariance!}
}
在这个例子中,IMyInterface<out T>
使用了 out
关键字,表示协变。这使得我们可以将 IMyInterface<string>
赋值给 IMyInterface<object>
。
这只是 C# 中一些高级泛型用法的简单示例。泛型约束、泛型委托、协变和逆变等概念可以帮助你更灵活地设计和使用泛型代码。
相关文章:
C# 泛型介绍
C# 中的泛型(Generics)是一种强类型参数化的特性,它允许你编写不具体指定数据类型的代码,而在实际使用时再指定具体的类型。泛型的引入使得代码更加灵活、可重用,并提高了类型安全性。 C#泛型基本用法 以下是一个简单…...

Windows如何正确设置PHP环境变量以在Git Bash中运行命令
1、随便找一个目录,鼠标右键打开git bash here 2、cd的根目录 3、找到php安装目录 4、 在根目录下打开 vim .bash_profile ,添加环境变量,php地址根据自己的本地地址而定 PATH$PATH:/d/phpstudy_pro/Extensions/php/php7.3.4nts 添加后保存…...

[代码实战和详解]VGG16
VGG16 详解 我的github代码实现:vgg16 我们在vgg16神经网络上训练了SIGNS数据集,这是一个分类的数据集,在我的github上有介绍怎么下载数据集以及如何训练。 VGG16是一个卷积神经网络(CNN)架构,它在2014年…...

x3daudio1_7.dll错误:解决方法和丢失原因及作用
x3daudio1_7.dll是Windows操作系统中的一个动态链接库(DLL)文件,主要作用是为DirectX音频提供支持。DirectX是微软推出的一套多媒体应用程序开发接口,广泛应用于游戏、多媒体制作等领域。x3daudio1_7.dll文件包含了许多与三维音频…...

pipeline + node +jenkins+kubernetes部署yarn前端项目
1、编写Dockerfile文件 # Set the base image FROM node:16.10.0# WORKDIR /usr/src/app/ WORKDIR /home/option# Copy files COPY ./ /home/option/# Build arguments LABEL branch${BRANCH} LABEL commit${COMMIT} LABEL date${BUILD_DATE} ARG ENV# Set ENV variables ENV …...
计算机网络中的面向连接与无连接
目录 面向连接和无连接在计算机网络中是如何理解的面向连接和无连接的通信在路由选择上有哪些区别 面向连接和无连接在计算机网络中是如何理解的 在计算机网络中,面向连接和无连接是两种核心的网络通信方式,它们决定了数据包如何传输和接收。 面向连接&…...
EventEmitter3在vue中的使用
前提 vue中的组件传递方式有很多,包括父子组件之间的传值(props,emit)、事件总线($ bus)、状态管理模式(vuex,pinia),现在推荐一种可以替代$bus的一种传值方…...

双剑合璧:基于Elasticsearch的两路召回语义检索系统,实现关键字与语义的高效精准匹配
搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…...

LeetCode34-34. 在排序数组中查找元素的第一个和最后一个位置
🔗:代码随想录:二分查找的算法讲解:有关left<right和left<right的区别 class Solution {public int[] searchRange(int[] nums, int target) {int nnums.length;int l0,hn-1;if(numsnull){return null; }if(n0){return new int[]{-1,-1}; }if(target&l…...
ddrnet 分割学习笔记
目录 修改后可以加载预训练: 训练自己的数据代码: 默认分割后特征下采样8倍,最后用上采样恢复到原图; 修改后可以加载预训练: import math import torch import numpy as np import torch.nn as nn import torch.nn.functional as F from torch.nn import init from …...

Outlook关闭过去事件的提醒
Outlook关闭过去事件的提醒 故障现象 最近Outlook中推出的新功能让我们可以选择自动关闭过去事件的提醒。 目前这个功能暂时只向当月通道的Office 365 订阅者发布。 这些用户升级到1810版本后,可以在不想收到已发生事件提醒的时候通过下面的步骤自动忽略过去事件…...
git 简单入门
git init touch test.txt git add test.txt git commit -m 初始化 仓库 git log //查找日志 git checkout -b dev //创建并切换dev分支 git branch // 查找分支 此时有master 和 dev分支, 此时在dev分支 dev分支也有test.txt文件 vim test.txt //写入dev …...

只有开源才能拯救AI
导语 | 随着 AI 技术的蓬勃发展,大模型的开源化正成为人工智能领域的新潮流,但同时引发的伦理和安全风险也饱受大家关注,如何把握平衡其中的尺度成为开源的一大难题。我们又应该如何有效进行开源治理?未来将走向何方?今…...

在Spring Boot中使用进程内缓存和Cache注解
在Spring Boot中使用内缓存的时候需要预先知道什么是内缓存,使用内缓存的好处。 什么是内缓存 内缓存(也称为进程内缓存或本地缓存)是指将数据存储在应用程序的内存中,以便在需要时快速访问和检索数据,而无需每次都从…...

YOLOv5项目实战(3)— 如何批量命名数据集中的图片
前言:Hello大家好,我是小哥谈。本节课就教大家如何去批量命名数据集中的图片,希望大家学习之后可以有所收获!~🌈 前期回顾: YOLOv5项目实战(1)— 如何去训练模型 YOLOv5项目实战(2...
React + hooks + Ts 实现将后端响应的文件流(如Pdf)输出到浏览器下载
React 篇 一些关于react 学习与总结 这篇是记录开发中关于实现将后端响应的文件流(如Pdf)输出到浏览器下载,基于React Hooks Ts。 开发场景: 实现将后端响应的文件流(如Pdf)输出到浏览器下载,…...
大数据基础设施搭建 - JDK
一、创建目录 需要在root账号下操作,因为/目录下只能用root账号创建目录 1.1 创建目录 [roothadoop102 ~]# mkdir /opt/software/ [roothadoop102 ~]# mkdir /opt/module/1.2 修改权限 修改module、software文件夹的所有者和所属组均为hadoop用户,远程使…...

从0到0.01入门React | 010.精选 React 面试题
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…...

Docker启动SRS流媒体服务器
一、安装Docker 1.1、下载windows桌面版Windows 1.2、配置镜像 镜像加速器镜像加速器地址Docker 中国官方镜像https://registry.docker-cn.comDaoCloud 镜像站http://f1361db2.m.daocloud.ioAzure 中国镜像https://dockerhub.azk8s.cn科大镜像站https://docker.mirrors.ustc…...
php+MySQL防止sql注入
1、使用预处理语句(Prepared Statements):预处理语句能够防止攻击者利用用户输入来篡改SQL语句,同时也能提高执行效率。通过将用户的输入参数与SQL语句分离,确保参数以安全的方式传递给数据库引擎,避免拼接…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...