(八)CSharp-泛型类和参数约束(1)

news2024/11/18 19:28:31

一、C# 中的泛型

泛型(generic)特性可以让多个类型共享一组代码。

泛型类型不是类型,而是类型的模板。

请添加图片描述

C# 提供了5种类型:类、结构、接口、委托和方法。

请添加图片描述

泛型类

请添加图片描述

泛型的主要优点:

  • 性能
    类型转换时,非泛型的类型进行装箱和拆箱时,会使得性能损失比较大。(需要转换运算符以及拷贝内存)

  • 类型安全
    如果在泛型类中,定义了具体类型,编译器就不会编译代码。

  • 二进制代码重用
    泛型可以定义一次,就可以用于不同类型的实例化。

  • 代码的扩展
    1)泛型类的定义会放在程序集中,所以用特定类型实例化泛型类不会在 IL 代码中复制这些类。(即类型实例化的代码在使用泛型时,不会进行拷贝这些实例化的代码)。
    2)在 JIT 编译器把泛型类编译为本地代码时,会给每个值类型创建一个新类引用类型共享同一个本地类的所有相同的实现代码。(比如 List《int》会对其类型进行复制,而 List《MyClass》会对其类型进行引用。)

  • 命名约定

命名规则:

泛型类型的名称用字母 T 作为前缀。
泛型类型允许用任意类替代,且只使用了一个泛型类型。

 public class List<T> { }
    public class LinkedList<T> { }
  • 如果泛型类型有特定的要求(例如,它必须实现一个接口或派生自基类),或者使用了两个或多个泛型类型,就应该泛型类型使用描述性的名称:
    //泛型委托
    public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
    public delegate TOutput Converter<TInput, TOutput>(TInput from);
    //泛型类
    public class SortedList<TKey, TValue> { }

二、声明泛型类

泛型声明定义的代码:

    //T1,T2 为类型参数
    class SomeClass<T1,T2>
    {
        public T1 SomeVar;
        public T2 OtherVar;
    }

    class Program
    {
        static void Main(string[] args)
        {
            //构造的类型
            var first = new SomeClass<short, int>();
            var second = new SomeClass<int, long>();

            Console.ReadKey();
        }
    }

执行测试代码的作用:

   //SomeClass<short, int>()
    class SomeClass<short,int>
    {
        public short SomeVar;
        public int OtherVar;
    }

   //SomeClass<int, short>()
    class SomeClass<int,short>
    {
        public int SomeVar;
        public short OtherVar;
    }
    

三、比较泛型和非泛型栈

实现泛型栈的代码例子:

    class MyStack<T>
    {
        T[] StackArray;
        int StackPointer = 0;

        public void Push(T x)
        {
            if (!IsStackFull)
                StackArray[StackPointer++] = x;
        }

        public T Pop()
        {
            return (!IsStackEmpty) ? StackArray[--StackPointer] : StackArray[0];
        }


        const int MaxStack = 10;
        bool IsStackFull { get { return StackPointer >= MaxStack; } }
        bool IsStackEmpty { get { return StackPointer <= 0; } }

        public MyStack()
        {
            StackArray = new T[MaxStack];
        }

        public void Print()
        {
            for (int i = StackPointer - 1; i >= 0; i--)
                Console.WriteLine($"  Value: { StackArray[i] }");

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyStack<int> StackInt = new MyStack<int>();
            MyStack<string> StackString = new MyStack<string>();

            StackInt.Push(3);
            StackInt.Push(5);
            StackInt.Push(7);
            StackInt.Push(9);
            StackInt.Print();

            StackString.Push("This is fun");
            StackString.Push("Hi there!  ");
            StackString.Print();
            Console.ReadKey();
        }
    }

表-非泛型栈和泛型栈之间的区别

非泛型泛型
源代码大小更大:需要为每一种类型编写一个新的实现(有重复的代码逻辑)更小:不管构造类型的数量有多少,只需要一个实现
可执行文件大小无论每一个版本的栈是否会被使用,都会在编译的版本中出现可执行文件中只会出现有构造类型的类型 (疑问:设计泛型类型的代码逻辑不在可执行文件里吗?似乎有些明白了,泛型只会放在程序集中,而不会拷贝这些实例化的代码,所以编译器不会编译设计泛型的代码。)
写的难易度易于书写,因为它更具体比较难写,因为它更抽象 (我觉得因为想要通用任何可支持的类型,需要考虑点多,越是抽象(类型特征越多),设计的代码结构就越复杂。)
维护的难易度更容易出问题,因为所有修改需要应用到每一个可用的类型上 (因为类型已固定了,如果更改类型或者代码结构,就会把所有应用到的地方都修改一遍,容易出错。)易于维护,因为只需要修改一个地方

四、类型参数的约束

1、类型参数的约束

由于泛型不知道它们保存的项的类型是什么,也就不会知道这些类型实现的成员,就不会对这些成员进行运算符的事情。

所以,如果泛型类需要调用泛型类型中的方法,就必须添加约束。

未绑定的类型参数: 符合约束的未绑定的类型参数。如果泛型里有 Object 成员,那么这个Object 成员是已知的类型,可以对它做一些如 ToSting、Equals 以及 GetType 方法的处理。而如果其他未知类型的成员不能像 Object 成员那样可以直接处理的,是未绑定的类型参数。

class Simple<T>
{
static public bool LessThan(T i1,T i2)
{
//错误,因为i1 和 i2 属于未绑定的类型参数,
//不能使用 < 运算符进行处理
retrun i1 < i2;
}
}

2、Where 子句

约束使用 where 子句列出。

  • 每一个有约束的类型参数都有自己的 where 子句。
  • 如果形参有多个约束,它们在 where 子句中使用逗号分隔。

where 子句的语法如下:

where TypeParam : constraint,constraint,...
//where:关键字
//TypeParam:类型参数
//constraint,constraint,...:约束列表

关于 where 子句的要点:

  • 它们在类型参数列表的关闭尖括号之后列出。
  • 它们不使用逗号或其他符号分隔。
  • 它们可以以任何次序列出。
  • where 是上下文关键字,所以可以在其他上下文中使用。
//T1 未绑定,T2 和 T3 具有约束
class MyClass < T1,T2,T3 >
		where T2:Customer //T2的约束
		where T3:IComparable //T3的约束
{
...
}

3、约束类型和次序

公有5种类型的约束:

约束类型描述
类名只有这个类型或从它派生的类才能用作类型实参
class任何引用类型,包括类、数组、委托和接口都可以用作类型实参
struct任何值类型都可以用作类型实参(包括枚举? 好吧,所有值类型,那就是包括枚举)
接口名只有这个接口或实现这个接口的类型才能用作类型实参
new()任何带有无参公共构造函数的类型都可以用作类型实参。这叫作构造函数约束

where 子句可以以任何次序列出。但是,where 子句中的约束必须有特定的顺序

  • 最多只能有一个主约束,而且必须放在第一位。
  • 可以有任意多的接口名称约束
  • 如果存在构造函数约束,则必须放在最后
约束约束类型个数
主约束ClassName class struct0或1个
次约束InterfaceName0或多个
构造函数约束new()0或1个
class SortedList<S>
		where S:IComparable<S>{...}

calss LinkedList<M,N>
		where M : IComparable<M>
		where M : ICloneable{...}

class MyDictonary<KeyType,ValueType>
		where KeyType:IEnumerable,
		new()               {...}

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

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

相关文章

2018~2019 学年第二学期《信息安全》考试试题(B 卷)

北京信息科技大学 2018 ~2019 学年第 2 学期 《信息安全》课程期末考试试卷 B 课程所在学院:计算机学院 适用专业班级:计科 1601-06&#xff0c;重修 考试形式:(闭卷) 一. 选择题(本题满分 10 分&#xff0c;共含 10 道小题&#xff0c;每小题 1 分) 网络中存在的安全漏洞主…

虚拟环境创建、配置及激活

虚拟环境创建、配置及激活 前言 一、虚拟环境是什么&#xff1f; 虚拟环境&#xff08;Virtual Environment&#xff09;是在计算机上使用特定版本的编程语言&#xff08;如python 3.9&#xff09;和其所需包及依赖项的一种方法(如pandas 2.4)&#xff0c;它可以被看作是一个隔…

基于html+css的图展示121

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

chatgpt赋能python:Python中如何快速删除字符串

Python中如何快速删除字符串 在Python编程中&#xff0c;字符串操作是非常常见的。有时候我们需要从字符串中删除一些无用的字符&#xff0c;以便更方便地处理数据。在本文中&#xff0c;将介绍Python如何快速删除字符串。 删除特定字符 Python中可以使用replace()函数快速替…

【深度学习炼丹大杀器——mlrunner初体验(以mmdetection为例)】

深度学习炼丹大杀器——mlrunner初体验&#xff08;以mmdetection为例&#xff09; 自动化炼丹&#xff0c;告别手动运行的烦恼~ 0.引言 了解深度学习的人都知道&#xff0c;炼丹是一种很玄学的事&#xff0c;并且还存在以下问题&#xff1a; 效率&#xff1a;在训练模型时&…

Seata服务端的启动过程 学习记录

1.ServerRunner ServerRunner类实现了CommandLineRunner与DisposableBean接口&#xff0c;将会在Spring容器启动和关闭的时间&#xff0c;分别执行 run 和 destory 方法。 而seata服务端的启动过程&#xff0c;都藏在run方法中 2.整体流程 io.seata.server.Server#start pu…

基于html+css的图展示120

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

【JMeter压力测试】通过jmeter压测surging

目录 前言 环境 下载配置源码 JMeter和JDK下载 JDKJmeter安装 Jmeter非GUI运行压测 结尾 前言 surging是异构微服务引擎&#xff0c;提供了模块化RPC请求通道&#xff0c;引擎在RPC服务治理基础之上还提供了各种协议&#xff0c;并且还提供了stage组件&#xff0c;以便针…

最新版CleanMyMac X4.13.4中文版Mac清理软件

cleanmymac是一款强大的Mac系统垃圾清理工具,可以清除Mac系统多余的语言包,系统缓存,应用程序!可智能清理mac磁盘垃圾和多余语言安装包&#xff0c;快速释放电脑内存&#xff0c;轻松管理和升级Mac上的应用。同时CleanMyMac X可以强力卸载恶意软件&#xff0c;修复系统漏洞&…

EXCEL函数2(统计函数,逻辑函数及其余函数)

统计函数 1、COUNT&#xff08;单元格范围&#xff09;&#xff1a; 计算单元格范围的行数&#xff0c;比如用光标选中一定范围内的单元格&#xff0c;那么只要单元格里面有值&#xff0c;那么count函数便会将有值的单元格的数量统计出来 2、COUNTA&#xff08;单元格范围&am…

msf渗透测试学习-与永恒之蓝漏洞案例

MSF是Metasploit Framework的缩写&#xff0c;是一款广泛使用的渗透测试工具&#xff0c;具有强大的攻击功能。它提供了一个模块化的平台&#xff0c;通过将各种攻击载荷、漏洞利用和辅助工具组装在一起&#xff0c;可用于模拟各种攻击&#xff0c;测试系统安全性&#xff0c;也…

Task Add-in Sample (C#)

下例显示了用 C# 编写Task Add-in 的完整源代码。 使用 C# 类库 &#xff08;.NET Framework&#xff09; 创建 Visual Studio 中的项目。实现 IEdmAddIn5。在“任务属性”对话框中创建自定义页。自定义任务详细信息页面。 注意&#xff1a; 若要填充下面的 GUID 属性&#x…

【linux】登录root账户时报错Sorry, that didn‘t work. Please try again.抱歉,这不管用,请再试一次

一、问题背景 登录其他普通账户的GUI桌面&#xff0c;发现都很正常&#xff0c;但是登录管理员账户root的桌面&#xff0c;重启之后一段时间正常&#xff0c;过一段时间就会出现登录报错Sorry, that didn’t work. Please try again. 二、解决办法——配置文件的解析 下面给出…

由于找不到msvcp120.dll丢失的解决方法,计算机丢失msvcp120.dll修复教程

在打开游戏或者软件的时候&#xff0c;计算机提示由于找不到msvcp120.dll&#xff0c;无法继续执行此代码怎么办呢&#xff1f;msvcp120.dll是一个动态链接库&#xff08;DLL&#xff09;文件&#xff0c;其作用是提供一些常用的C函数和类库&#xff0c;以便在Windows操作系统上…

高手都是如何做 Mysql 慢 SQL 优化

tip&#xff1a;作为程序员一定学习编程之道&#xff0c;一定要对代码的编写有追求&#xff0c;不能实现就完事了。我们应该让自己写的代码更加优雅&#xff0c;即使这会费时费力。 &#x1f495;&#x1f495; 推荐&#xff1a;体系化学习Java&#xff08;Java面试专题&#…

2017~2018学年《信息安全》考试试题(A2卷)

北京信息科技大学&#xff0c;2017~2018 学年第二学期《信息安全》考试试题&#xff08;A 卷&#xff09; 适用专业班级&#xff1a;计科15级 重修课程所在学院&#xff1a;计算机学院 考试形式&#xff1a;闭卷 一、单选题&#xff08;本题满分20分&#xff0c;共含10 道小题…

《Java从入门到精通》学习笔记

Java从入门到精通学习笔记 第一章 初识java a) Java是一种通过解释方式来执行的语言。 b) Java语言编写的程序既是编译型&#xff0c;又是解释型的。编译只进行一次&#xff0c;而解释在每次运行程序时都会进行。 c) JDK下载安装 i. path:jdk/bin ii. calsspath:jdk/jre/lib ii…

融合动态反向学习的阿奎拉鹰与哈里斯鹰混合优化算法(DAHHO)-附代码

融合动态反向学习的阿奎拉鹰与哈里斯鹰混合优化算法(DAHHO) 文章目录 融合动态反向学习的阿奎拉鹰与哈里斯鹰混合优化算法(DAHHO)1.哈里斯鹰优化算法2.改进哈里斯鹰优化算法2.1 动态反向学习策略2.2 改进混合算法理论分析 3.实验结果4.参考文献5.Matlab代码6.python代码 摘要&a…

融合黄金正弦和随机游走的哈里斯鹰优化算法(GSHHO)-附代码

融合黄金正弦和随机游走的哈里斯鹰优化算法(GSHHO) 文章目录 融合黄金正弦和随机游走的哈里斯鹰优化算法(GSHHO)1.哈里斯鹰优化算法2.改进哈里斯鹰优化算法2.1 黄金正弦算法2.2 非线性能量指数递减策略2.3 高斯随机游走策略 3.实验结果4.参考文献5.Matlab代码6.python代码 摘要…

【软件环境安装部署】华为云服务器下 Docker 安装 MongoDB 以及 SpringBoot 整合 MongoDB 开发使用

文章目录 安装测试 MongoDB拉取镜像创建和启动容器登录mongo容器&#xff0c;并进入到【admin】数据库创建一个用户&#xff0c;mongo 默认没有用户连接mongo数据库测试数据库&#xff0c;插入一条语句测试数据库&#xff0c;查询刚才插入的语句查看所有数据库开放指定端口开放…