自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(1663)
  • 收藏
  • 关注

原创 函数形参和实参的传递机制及内存分配的理解

形参变量是函数进入时在栈上分配的(参数被拷贝到形参变量所在的栈内存上,所以形参改变值只是改变了实际参数的备份并不影响函数外的实际参数;只有传送指针等引用传递的参数才能影响实参变量的值),函数结束后被释放。

2024-09-15 09:35:48 72

原创 C++和C#在内存处理上的比较

C#与C++内存管理的比较(【出处】http://blog.csdn.net/hardwayboy/article/details/4499242)1、总述C#最大的一个改进其实就是对内存访问与管理方法的改进。在.NET中内存的管理是全权委托给垃圾回收器,由垃圾回收器来决定何时该释放内存空间。现在普遍采用两种技术来释放程序动态申请的系统内存:首先是以C++为代表的必须以手工方式使应用程序代码完成这些工作,让对象维护引用计数。然后是以.NET以及Java使用的垃圾回收器来完成内存释放工作。在C++

2024-09-15 09:32:34 1057

原创 Qt中使用Mysql并发读写

在进行多线程并发读写MySQL数据库之前,需要安装Qt和MySQL数据库,并确保Qt中已经集成了相应的数据库插件。通过将不同的数据库操作放在不同的线程中,可以实现并发读写数据库。/*************************************mysql数据库多线程写入 多线程操作mysql。/***********************************Qt mysql多线程并发读写。/********************************QT数据库连接初始化和删除的方法。

2024-08-18 11:29:29 869

原创 解决C++开发中的内存碎片问题的几种方式

内存碎片指的是已分配的内存块在使用过程中出现断开的情况,导致可分配的连续内存空间变少,从而影响程序的性能和稳定性。通过使用内存池,可以避免频繁的内存分配和释放,从而减少内存碎片的产生。在C++中,内存碎片是指可用内存空间的分割,它导致即使有足够总量的空闲内存,也可能无法满足较大内存块的分配请求。1.对象池:通过预分配一定数量的对象内存,然后自己管理内存池的分配和释放,可以减少对系统内存的频繁申请和释放。/**************************解释C++中的内存碎片及其影响。

2024-08-18 11:13:41 448

原创 c++中在堆上创建数组

i == 10 的时候,数组下标范围是0~9,并没有a[10]这个元素,所以程序会导致越界,其结果是未定义的(不确定的)。堆数组,就是指一次性从堆内存分配连续的多个无名变量(也叫元素),这些变量(元素)的地址前后紧挨在一起。下面的代码创建了10个连续存放的无名整型变量(元素),其中第一个变量的地址是a。为了使用这些连续的无名变量(元素),数组使用下标(索引,中括号)来访问这些元素。注意:a[9]是最后一个元素,因为下标是从0,而不是1开始的。注意看第一个元素的下标是0,第10个元素的下标是9。

2024-08-18 11:09:48 198

原创 QT使用Sqlite多线程注意事项

如果没有指定标识,或者使用sqlite3_open()或sqlite3_open16()函数来创建数据库连接,那么在编译时或启动时指定的线程模式将作为默认的线程模式使用。由于sqlite3_threadsafe()函数要早于多线程模式以及启动时和运行时的模式选择,所以它既不能区别多线程模式和串行模式也不能区别启动时和运行时的模式。一般而言,运行时指定的模式将覆盖启动时的指定模式,启动时指定的模式将覆盖编译时指定的模式。如果在编译时或启动时指定为单线程模式,就无法在创建连接时指定多线程或者串行模式。

2024-08-18 10:54:12 296

原创 QML中使用信号槽的几种方法

如果有多个对象使用objectName:"qml_button"同名标记,QObject::findChild返回最后一个标记的QML对象,QObject::findChildren返回所有标记的QML对象存放在QList类型的列表中。在启动QML时,会初始化一个QQmlEngine作为QML引擎,然后使用QQmlComponent对象加载QML文档,QML引擎会提供一个默认的QQmlContext对象作为顶层执行的上下文,用来执行QML文档中定义的函数和表达式。

2024-07-27 21:39:48 686

转载 计算机系统中程序中断的基本概念 ,中断分类 ,流程详解

排队器的输出是对各个中断信号择优后的一个信号,此时对应一个中断源信号,此时通过中断向量地址形成部件生成中断向量地址,中断向量地址存储的指令可以跳转到中断处理程序的入口地址(中断向量就是中断处理程序的地址)为何要使用中断向量地址的形式,如果中断向量地址形成部件直接生成中断处理程序的地址,那么当中断处理程序的地址改变,那么此时需要修改中断形成部件的电路结构以生成对应的修改后的中断处理程序地址,这样很麻烦。为此,要进行中断排队。关中断使得中断服务程序一气呵成,不会被其他中断打断,直到中断服务程序结束时再开中断。

2024-07-12 20:20:32 1758

原创 51单片机的中断系统详解

51系列单片机的中断源包括:两个外部中断源、两个定时器/计数器中断源和一个串行通信口中断源,如果它们向 CPU 发出中断请求信号,CPU 就会产生中断,停止执行当前的程序,转而去执行指定的程序(又称中断服务程序或中断子程序),执行完后又返回来执行原来的程序。将生活事例与单片机中断结合分析,主任务是洗衣服,水开报警是一个中断请求,这一时刻相当于断点处,响应中断去关火,然后将开水灌入暖水瓶中,这一动作实际上是处理中断程序,灌完开水后再回去继续洗衣服,相当于处理完中断程序后再返回主程序继续执行主程序。

2024-07-09 22:20:28 1289

原创 单片机系统中的多任务多线程机制的实现详解

另一方面,单片机自从80年代诞生以来,便以飞快的速度发展起来,但由于其物理条件的限制,单片机控制系统的编程仍然局限于经验的模式,很少应用那些新提出的高级语言的编程思想。这对软件的设计有了很高的要求,这同时也是单片机控制系统用软件模拟多线程方法中的难点之一,为了解决这个问题,可在个线程自带线程进度指示器用来标志线程的运行进度,即用一个变量记载线程的每一步。这里我们把每一个启动通道进行测试的程序叫做一个任务,把各自任务下的每一个单独的、分开处理的程序段叫做一个线程,每个线程依靠自己的标识来识别。

2024-07-09 22:07:37 1281

原创 C# 中GDI绘制后不显示问题原因分析与解决,与控件重绘相关的方法区别

系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由 系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由 系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;即在其显示之前画什么都是无用的。

2024-07-06 22:39:10 714

原创 c#中窗口句柄有关的问题详解

窗口创建时,窗口并没有创建句柄,只有Application.Run(form)或者form.Show()之后才有句柄,即窗口只有显示或者启动消息循环后才有句柄!如果创建form之后Form form = new Form(),主线程中调用form.Handle,如果句柄尚未创建,引用该属性将强制创建句柄,对系统内的逻辑将产生致命的影响。(7)、IsHandleCreated :指示控件是否有与他关联的句柄,如果已经为控件分配了句柄,则为 true;(2)、CreateHandle :为该控件创建句柄,

2024-07-06 22:22:19 489

原创 C# 自定义事件(EventArgs)使用实例

为了激发用户控件的新增事件,修改了一下代码,接下去在用户控件中添加事件,

2024-07-06 22:19:33 376

原创 深入了解UDP 服务器与客户端区别

recvfrom() 函数的返回值是二元组 (bytes, address),其中 bytes 是接收到的 bytes 对象数据,address 是发送方的 IP 地址与端口号,用二元组 (host, port) 表示。可见,UDP 的通信过程比 TCP 简单许多,服务器少了监听与接受连接的过程,而客户端也少了请求连接的过程。type 参数代表套接字的类型,默认值为 SOCK_STREAM,用于 TCP 协议(面向连接)的网络通信,常用的还有 SOCK_DGRAM,用于 UDP 协议(无连接)的网络通信。

2024-07-06 22:17:23 1364

原创 CPU架构及原理

存储单元:包括CPU片内缓存和寄存器组,是CPU中暂时存放数据的地方,里面保存着那些等待处理的数据,或已经处理过的数据,CPU访问寄存器所用的时间要比访问内存的时间短。OK,总结一下,CPU的运行原理就是:控制单元在时序脉冲的作用下,将指令计数器里所指向的指令地址(这个地址是在内存里的)送到地址总线上去,然后CPU将这个地址里的指令读到指令寄存器进行译码。相对控制单元而言,运算器接受控制单元的命令而进行动作,即运算单元所进行的全部操作都是由控制单元发出的控制信号来指挥的,所以它是执行部件。

2024-06-06 22:35:15 717

原创 汇编基础知识-寄存器

IP是专用寄存器,具有自动增量的能力,处理完一条指令,IP的值就加上该指令的字节数,从而指向下一条指令,实现程序的顺序执行。CF(进位标志)、PF(奇偶标志)、AF(调整标志)、ZF(零标志)、SF(符号标志)、OF(溢出标志)(4)没有合适的高级语言或只能采用汇编语言时,如开发最新的处理器程序、暂时没有支持新指令的编译程序。(2)执行:将指令代码翻译成它代表的功能(译码),并发出有关控制信号实现这个功能。(1)原码——最高有效位表示符号(正0负1),其它位直接表示数值大小。bp寄存器默认是SS。

2024-06-01 22:26:59 1422

原创 计算机控制系统之CPU组成及原理(内存寄存器)

而当除数是 16 位时,被除数一定是 32 位的,因为 AX 是 16 位寄存器,自然,放不下 32 位的被除数,所以,在这里还需要使用另一个 16 位寄存器 DX ,其中 DX 存放 32 位的被除数的高 16 位,而 AX 则存放 32 位的被除数的低 16 位,同时,AX 的作用还不仅仅是用来保存被除数的,当除法指令执行完成以后,当然,如果除数是 16 位的话,则 AX 中会保存本次除法操作的商,而 DX 则保存本次除法操作的余数。程序的开始过程和顺序流程是一样的,程序的顺序流程和开始过程相同。

2024-05-30 21:37:31 1784

原创 c及c++基础概念:寄存器、内存、堆栈之间的关系和原理详解

寄存器寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果,包括通用寄存器、专用寄存器和控制寄存器。其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。内存

2024-05-30 21:23:46 2636

原创 c#跳转语句详解

即为标签名,再加上冒号":",标签名大家可以随意取,比如aa,bb,反正随大家喜欢.这四句代码的意思是,第一句:定义变量i,第二句:跳转到标签为cc的语句,接下来就输出i的结果,可以看出,第三句是无意义的,因为没有被执行,跳过去了,所以输出的值是0,而不是9.goto 的意思是跳转到的意思,那么跳转到哪里呢,当然是跳转到另一个语句,如何标示这个要跳转到的语句,答案是在该语句前加上标签。goto跳转的语句,并不是一定要跳转到之后的语句,也就是说,goto还可以跳到前面去执行。输出结果:从这里继续执行...

2024-05-29 20:19:43 759

原创 C#设计模式之订阅发布模式详解(实例演示)5

/订阅者C(注意:构造函数中有注册的方法,所以每创建一次实例对应的实例默认都为发布者注册了一次)//创建订阅者(构造函数内部被注册到发布者了,所以后面不用再注册了)//创建订阅者(构造函数内部被注册到发布者了,所以后面不用再注册了)//订阅者收到发布者的通知后要执行的方法(被注册的方法)//订阅者收到发布者的通知后要执行的方法(被注册的方法)//订阅者收到发布者的通知后要执行的方法(被注册的方法)// //发布者通知,所有注册者的注册方法都被执行了。//发布者通知,所有注册者的注册方法都被执行了。

2024-05-23 22:57:37 302

原创 C#设计模式之订阅发布模式详解4

通过如上代码我们试着去解决我们第一处所说的问题,我们会发现使用event关键字后可以保护我们OnChange免受不必要的访问。如果说我们觉得如上的过程不是我们预期的,我们需要手动引发事件并处理异常,这时候我们可以使用Delegate基类中定义的GetInvoctionList来帮助我们实现这些。如上代码我们创建了一个发布者,并且我们调用委托进行创建我们匿名方法来订阅。运行如上代码后,大家会发现第一个订阅者已经执行成功了,第二个订阅者引发了异常,而第三个订阅者未被调用.这是一个很尴尬的事情.

2024-05-17 21:07:57 618

原创 C#中事件:发布订阅模式实例详解3

委托可以使用额外的运算符来组合.这个运算最终会创建一个新的委托,其调用列表是两个操作数的委托调用列表的副本连接.委托是恒定的,操作数委托创建后不会被改变,委托组合拷贝的是操作数的副本。在Main方法中,我们需要构建几个Rat对象和一个Cat对象,将Rat对象添加到Cat对象的集合中,调用Cat对象的Shout方法。委托存储的是一系列具有相同签名和返回值类型的方法的地址,调用委托的时候,委托包含的所有方法将被执行。(只是一个测试 不写的很详细了 还是拿猫和老鼠举例子 猫类和老鼠类 以及定义的委托的代码如下)

2024-05-17 21:03:42 586

原创 C#中事件:发布订阅模式实例详解2

Console.WriteLine("AEvent add被调用,value的HashCode为:" + value.GetHashCode());当事件被触发的时候,订阅者得到通知,而订阅者所提交的所有方法都会被执行。Console.WriteLine("触发对象:{0}, 保存信息:{1}", sender.ToString(), e.Information);Console.WriteLine("触发对象:{0}, 保存信息:{1}", info, sender.ToString());

2024-05-17 20:55:48 1035

原创 C#发布订阅模式详解

Console.WriteLine($"{name}收到{work.name}的工作, 大概需要{work.workLoad/workSpeed}分钟, {boss.name}.");实现发布订阅模式的土方法:声明委托类,在发布者类中声明委托类成员,定义发布方法(事件触发),声明订阅类,在订阅类中声明订阅方法(绑定到订阅者的委托(事件)成员中)。Console.WriteLine($"\n{this.status} -> {status} 大家开始学习嗷");", works);// 调用事件触发方法.

2024-05-17 20:48:38 823

原创 C#中的事件(委托的发布和订阅、事件的发布和订阅、EventHandler类、Windows事件)实例详解,观察者(Observer)模式也称发布-订阅(Publish-Subscribe)模式

object类型的参数sender表示引发事件的对象,由于事件成员只能由类型本身(即事件的发布者)触发,因此在触发时传递给该参数的值通常为this。引发事件的对象称为事件的源或发送者。在事件发布和订阅的过程中,定义事件的类型(即委托类型)是一件重复性的工作,为此,.NET类库中定义了一个EventHandler委托类型,并建议尽量使用该类型作为事件的委托类型。事件是类的一种特殊成员:即使是公有事件,除了其所属类型之外,其他类型只能对其进行订阅或取消,别的任何操作都是不允许的,因此事件具有特殊的封装性。

2024-05-16 22:26:11 1524

原创 C#中实现一个安全的事件订阅器实例

接受消息的方法

2024-05-16 22:12:58 591

原创 编程中事件驱动架构概述

现在的技术发展快,前后端不断涌现各种框架,我们恨不得把这些框架都用在自己的项目里才行,按实际出发,按需所用,适当的预留技术预研的空间。事件具有自己的属性,比如发生的时间、发生了什么、事件之间的关系、状态以及变化,事件也可以生成新的事件,根据不同的事件生成新的业务事件。事件溯源是一个特别的思路,它并不持久化实体对象,而是只把初始状态和每次变更的事件记录下来,并在内存中根据事件还原实体对象的最新状态,mysql主从备份用到的binary log以及redis的aof持久化机制,都可以认为是“事件溯源”的实现。

2024-05-16 21:53:32 444

原创 C#用S7.net.dll控制西门子S1200PLC

Read还有一个按偏移量去读取的,可以批量连续读取相同数据类型的,我这里的案例就只读一个出来,为了演示而已。类写入的情况一样我们要用到刚刚建立的类,然后给类赋值,这里使用DB3块做样例。DataType:数据存储的位置类型。DataType:数据存储的位置类型。DataType:数据存储的位置类型。count:结束的偏移量位置,也可以理解读取多少个位数据上来。rack:机台号的位置,这个也是PLC的知识点。slot:插槽号的位置,也是PLC的知识点。startByteAdr:开始的偏移量位置。

2024-05-14 19:59:02 1879

原创 c#中子线程和主线程交叉引用阻塞问题解决办法

方案2: // info.BeginInvoke(new Action(() =>//此处阻塞原因是因为info的子线程和主线程在其他地方交叉使用了,此处造成了子线程阻塞,导致此处的主线程也阻塞了,而恰好其他地方又使用了主线程,陷入了死循环。方案1:// Task.Factory.StartNew(() => {//加入子线程来执行这块逻辑,如能通过则下面的猜想是对的,经验证与所述一致。(所以可以用多线程或BeginInvoke解决此阻塞问题)//注意:防止子线程和主线程交叉引用后的阻塞问题。

2024-05-14 19:49:22 198

原创 c#中泛型委托,方法的声明及定义实例(全)

泛型很适用于集合,我们常见的泛型集合有:List<T>,Dictionary<K,V>等等(T,K,V就代表不确定的类型,它是一种类型占位符,当然你也可以使用其他符号代替,只不过一般常规都是用T,T1,T2这种,如A,B,C,AA,BB,ABC...等等都可以,甚至一个单词或汉字也可以,因为编译器最终编译的时候会将这些占位符替换成对应的实际类型,也就是泛型要使用的实例的类型),无一不是利用的泛型这一特性,若没有泛型,我们会多出很多重载方法,以解决类型不同,但是执行逻辑相同的情况。

2024-05-13 22:51:47 875

原创 C语言预处理命令总结说明

后是指令关键字,在关键字和 # 号之间允许存在任意个数的空白字符,整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的,程序员在程序中用预处理命令来调用这些功能。条件编译允许只编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。#elif 如果前面的#if给定条件不为真,当前条件为真,则编译下面代码。#ifdef 如果宏已经定义,则编译下面代码。

2024-05-01 20:51:30 158

原创 C语言#include的用法详解(文件包含命令)详解

#include叫做文件包含命令,用来引入对应的头文件(.h文件)。#include 也是C语言预处理命令的一种。#include 的处理过程很简单,就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件,这与复制粘贴的效果相同。#include 的用法有两种,如下所示:#include <stdHeader.h>#include "myHeader.h"使用尖括号< >和双引号" "的区别在于头文件的搜索路径不同:使用尖括号< &

2024-05-01 20:50:32 2575

原创 C语言各种预处理命令详解

但是现在有个问题,程序中要实现的某个功能在 VS 和 GCC 下使用的函数不同(假设 VS 下使用 a(),GCC 下使用 b()),VS 下的函数在 GCC 下不能编译通过,GCC 下的函数在 VS 下也不能编译通过,怎么办呢?不同的平台下必须调用不同的函数,并引入不同的头文件,否则就会导致编译错误,因为 Windows 平台下没有 sleep() 函数,也没有 <unistd.h> 头文件,反之亦然。你看,在不同的平台下,编译之前(预处理之后)的源代码都是不一样的。这种以#号开头的命令称为预处理命令。

2024-05-01 20:48:38 328

原创 C语言指针是什么?彻底理解C语言指针的概念

当程序被加载到内存后,操作系统会给不同的内存块指定不同的权限,拥有读取和执行权限的内存块就是代码,而拥有读取和写入权限(也可能只有读取权限)的内存块就是数据。需要注意的是,虽然变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符,但在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名、字符串名和数组名表示的是代码块或数据块的首地址。( )表示取值操作,整个表达式的意思是,取出地址 0X1000 和 0X2000 上的值,将它们相加,把相加的结果赋值给地址为 0X3000 的内存。

2024-05-01 20:45:11 361

原创 C语言指针变量的定义和使用详解(精华)

上节我们说过,CPU 读写数据必须要知道数据在内存中的地址,普通变量和指针变量都是地址的助记符,虽然通过 *p 和 a 获取到的数据一样,但它们的运行过程稍有不同:a 只需要一次运算就能够取得数据,而 *p 要经过两次运算,多了一层“间接”。值得注意的是,p_a 需要的一个地址,a 前面必须要加取地址符&,否则是不对的。*&a可以理解为*(&a),&a表示取变量 a 的地址(等价于 pa),*(&a)表示取这个地址上的数据(等价于 *pa),绕来绕去,又回到了原点,*&a仍然等价于 a。

2024-05-01 20:43:43 64

原创 C语言指针数组详解(数组每个元素都是指针)

parr 是指向数组 arr 的指针,确切地说是指向 arr 第 0 个元素的指针,它的定义形式应该理解为int *(*parr),括号中的*表示 parr 是一个指针,括号外面的int *表示 parr 指向的数据的类型。第二个 printf() 语句中,parr+i 表示第 i 个元素的地址,*(parr+i) 表示获取第 i 个元素的值(该元素是一个指针),**(parr+i) 表示获取第 i 个元素指向的数据。为了便于理解,可以将上面的字符串数组改成下面的形式,它们都是等价的。

2024-05-01 20:42:08 293

原创 C语言函数指针(指向函数的指针)详解示例演示

一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。注意( )的优先级高于*,第一个括号不能省略,如果写作returnType *pointerName(param list);//返回两个数中较大的一个。

2024-05-01 20:40:54 284

原创 C语言指针的总结详解(1)

程序在运行过程中需要的是数据和指令的地址,变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符:在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名、字符串名和数组名表示的是代码块或数据块的首地址;5) 数组也是有类型的,数组名的本意是表示一组类型相同的数据。2) 给指针变量赋值时,要将一份数据的地址赋给它,不能直接赋给一个整数,例如int *p = 1000;p 可以指向 int 类型的数据,也可以指向类似 int arr[n] 的数组。定 义 含 义。

2024-05-01 20:39:15 152

原创 c#中泛型方法的声明及定义实例(2-2)

泛型很适用于集合,我们常见的泛型集合有:List,Dictionary等等(T,K,V就代表不确定的类型,它是一种类型占位符),无一不是利用的泛型这一特性,若没有泛型,我们会多出很多重载方法,以解决类型不同,但是执行逻辑相同的情况。/实例演示******************************************************************//************************************ 泛型方法声明定义及使用。

2024-04-29 21:05:38 998

原创 C#中泛型详解(4)

在泛型类型或方法定义中,类型参数是在其实例化泛型类型的一个变量时,客户端指定的特定类型的占位符。从上面的结果中我们可以看出这三个方法,除了传入的参数不同外,其里面实现的功能都是一样的。泛型是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。从上面的结果中我们可以看出,使用Object类型达到了我们的要求,解决了代码的可复用。可以看到,在泛型接口的T前面有一个out关键字修饰,而且T只能是返回值类型,不能作为参数类型,这就是协变。这样会造成类型不安全的问题。

2024-04-29 20:57:30 485

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除