C#高级编程笔记-泛型
本章的主要内容如下:
● 泛型概述
● 创建泛型类
● 泛型类的特性
● 泛型接口
● 泛型结构
● 泛型方法
目录
1.1 泛型概述
1.1.1 性能
1.1.2 类型安全
1.1.3 二进制代码的重用
1.1.4 代码的扩展
1.1.5 命名约定
1.2 创建泛型类
1.3 泛型类的功能
1.3.1 默认值
1.3.2 约束
1.3.3 继承
1.3.4 静态成员
1.4 泛型接口
1.4.1 协变和抗变
1.4.2 泛型接口的协变
1.4.3 泛型接口的抗变
1.5 泛型结构
1.6 泛型方法
1.6.1 带委托的泛型方法
1.1 泛型概述
泛型是C#和.NET的一个重要概念。泛型不仅是C#编程语言的一部分,而且与程序集中的L(Intermediate Languag,中间语言)代码紧密地集成。有了泛型,就可以创建独立于被包含类型的类和方法。我们不必给不同的类型编写功能相同的许多方法或类,只创建一个方法或类即可。
另一个减少代码的选项是使用Object类,但使用派生自Object类的类型进行传递不是类型安全的。泛型类使用泛型类型,并可以根据需要用特定的类型替换泛型类型。这就保证了类型安全性:如果某个类型不支持泛类,编译器就会出现错误。
泛型不仅限于类,本章还将介绍用于接口和方法的泛型。用于委托的泛型参见第8章。
泛型不仅存在于C#中,其他语言中有类似的概念。例如,C+模板就与泛型相似。但是,C+模板和NET泛型之间有一个很大的区别。对于C+模板,在用特定的类型实例化模板时,需要模板的源代码。C十+编译器为每个属于特定模板实例的类型生成单独的二进制代码。相反,泛型不仅是C#语言的一种结构,而且是CLR(公共语言运行库定义的。所以,即使泛型类是在C#中定义的,也可以在Visual Basic中用一个特定的类型实例化该泛型。
下面介绍泛型的优点和缺点,尤其是:
● 性能
● 类型安全性
● 二进制代码重用
● 代码的扩展
● 命名约定
1.1.1 性能
泛型的一个主要优点是性能。第10章介绍了System.Collections和System.Collections. Generic命名空间的泛型和非泛型集合类。对值类型使用非泛型集合类,在把值类型转换为引用类型,和把引用类型转换为值类型时,需要进行装箱和拆箱操作。
下面的例子显示了System.Collections命名空间中的ArrayList类。ArrayList存储对象, Add()方法定义为需要把一个对象作为参数,所以要装箱一个整数类型。在读取ArrayList中的值时,要进行拆箱,把对象转换为整数类型。可以使用类型转换运算符把ArrayList集合的第一个元素赋予变量i1,在访问int类型的变量i2的foreach语句中,也要使用类型转换运算符:
装箱和拆箱操作很容易使用,但性能损失比较大,迭代许多项时尤其如此。
System.Collections.Generic命名空间中的List<T>类不使用对象,而是在使用时定义类型。在下面的例子中,List<T>类的泛型类型定义为int,所以int类型在JIT编译器动态生成的类中使用,不再进行装箱和拆箱操作。
1.1.2 类型安全
泛型的另一个特性是类型安全。与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。下面的例子在ArrayList类型的集合中添加一个整数、一个字符串和一个MyClass类型的对象:
如果这个集合使用下面的foreach语句迭代,而该foreach语句使用整数元素来迭代,编译器就会编译这段代码。但并不是集合中的所有元素都可以转换为int,所以会出现一个运行异常:
错误应尽早发现。在泛型类List<T>中,泛型类型T定义了允许使用的类型。有了List<int>的定义,就只能把整数类型添加到集合中。编译器不会编译这段代码,因为Add()方法的参数无效:
1.1.3 二进制代码的重用
泛型允许更好地重用二进制代码。泛型类可以定义一次,用许多不同的类型实例化。不需要像C++模板那样访问源代码。
例如,System.Collections.Generic命名空间中的List<T>类用一个int、一个字符串和一个MyClass类型实例化:
泛型类型可以在一种语言中定义,在另一种.NET语言中使用。
1.1.4 代码的扩展
在用不同的类型实例化泛型时,会创建多少代码?
因为泛型类的定义会放在程序集中,所以用某个类型实例化泛型类不会在IL代码中复制这些类。但是,在JIT编译器把泛型类编译为内部码时,会给每个值类型创建一个新类。引用类型共享同一个内部类的所有实现代码。这是因为引用类型在实例化的泛型类中只需要4字节的内存单元(32位系统),就可以引用一个引用类型。值类型包含在实例化的泛型类的内存中。而每个值类型对内存的要求都不同,所以要为每个值类型实例化一个新类。
1.1.5 命名约定
如果在程序中使用泛型,区分泛型类型和非泛型类型会有一定的帮助。下面是泛型类型的命名规则:
● 泛型类型的名称用字母T作为前缀。
● 如果没有特殊的要求,泛型类型允许用任意类替代,且只使用了一个泛型类型,就可以用字符T作为泛型类型的名称。
● 如果泛型类型有特定的要求(例如必须实现一个接口或派生于基类),或者使用了两个或多个泛型类型,就应给泛型类型使用描述性的名称:、
1.2 创建泛型类
首先介绍一个一般的、非泛型的简化链表类,它可以包含任意类型的对象,以后再把这个类转化为泛型类。
在链表中,一个元素引用其后的下一个元素。所以必须创建一个类,将对象封装在链表中,引用下一个对象。类LinkedListNode包含一个对象value,它用构造函数初始化,还可以用Value属性读取。另外,LinkedListNode类包含对链表中下一个元素和上一个元素的引用,这些元素都可以从属性中访问。
LinkedList类包含LinkedListNode类型的first和last字段,它们分别标记了链表的头尾。AddLast()方法在链表尾添加一个新元素。首先创建一个LinkedListNode类型的对象。如果链表是空的,则first和last字段就设置为该新元素;否则,就把新元素添加为链表中的最后一个元素。执行GetEnumerator()方法时,可以用foreach语句迭代链表。GetEnumerator()方法使用yield语句创建一个枚举器类型。
现在可以给任意类型使用LinkedList类了。在下面的代码中,实例化了一个新LinkedList对象,添加了两个整数类型和一个字符串类型。整数类型要转换为一个对象,所以执行装箱操作,如前面所述。在foreach语句中执行拆箱操作。在foreach语句中,链表中的元素被强制转换为整数,所以对于链表中的第三个元素,会发生一个运行异常,因为它转换为int时会失败。
下面创建链表的泛型版本。泛型类的定义与一般类类似,只是要使用泛型类型声明。之后,泛型类型就可以在类中用作一个字段成员,或者方法的参数类型。LinkedListNode类用一个泛型类型T声明。字段value的类型是T,而不是object。构造函数和Value属性也变为接受和返回T类型的对象。也可以返回和设置泛型类型,所以属性Next和Prev的类型是LinkedListNode<T>。
1.3 泛型类的功能
在创建泛型类时,需要一些其他C#关键字。例如,不能把null赋予泛型类型。此时,可以使用default关键字。如果泛型类型不需要Object类的功能,但需要调用泛型类上的某些特定方法,就可以定义约束。
本节讨论如下主题:
● 默认值
● 约束
● 继承
● 静态成员
下面开始一个使用泛型文档管理器的示例。文档管理器用于从队列中读写文档。先创建一个新的控制台项目DocumentManager,添加类DocumentManager<T>。AddDocument()方法将一个文档添加到队列中。如果队列不为空,IsDocumentAvailable只读属性就返回true。
1.3.1 默认值
现在给DocumentManager<T>类添加一个GetDocument()方法。在这个方法中,给类型T指定null。但是,不能把null赋予泛型类型。原因是泛型类型也可以实例化为值类型,而null只能用于引用类型。为了解决这个问题,可以使用default关键字。通过default关键字,将null赋予引用类型,将0赋予值类型。
1.3.2 约束
如果泛型类需要调用泛型类型上的方法,就必须添加约束。对于DocumentManager<T>,文档的所有标题应在DisplayAllDocuments()方法中显示。Document类实现带有Title和Content只读属性的IDocument接口。
要使用DocumentManager<T>类显示文档,可以将类型T强制转换为IDocument接口,以显示标题:
问题是,如果类型T没有执行IDocument接口,这个类型转换就会生成一个运行异常。最好给DocumentManager<TDocument>类定义一个约束:TDocument类型必须执行IDocument接口。为了在泛型类型的名称中指定该要求,将T改为TDocument。where子句指定了执行IDocument接口的要求。
这样,就可以编写foreach语句,让类型T包含属性Title了。Visual Studio IntelliSense和编译器都会提供这个支持。
在Main()方法中,DocumentManager<T>类用Document类型实例化,而Document类型执行了需要的IDocument接口。接着添加和显示新文档,检索其中一个文档:
DocumentManager现在可以处理任何执行了IDocument接口的类。
在示例应用程序中,介绍了接口约束。泛型还有几种约束类型,如表9-1所示。
注意·:
在C#中,where子句的一个重要限制是,不能定义必须由泛型类型执行的运算符。运算符不能在接口中定义。在where子句中,只能定义基类、接口和默认构造函数。
1.3.3 继承
前面创建的LinkedList<T>类执行了IEnumerable<T>接口:
泛型类型可以执行泛型接口,也可以派生于一个类。泛型类可以派生于泛型基类:
其要求是必须重复接口的泛型类型,或者必须指定基类的类型,如下所示:
于是,派生类可以是泛型类或非泛型类。例如,可以定义一个抽象的泛型基类,它在派生类中用一个具体的类型实现。这允许对特定类型执行特殊的操作:
还可以创建一个部分的特殊操作,如从Quey中派生StringQuery类,只定义一个泛型参数,如字符事 TResult。要实例化StringQuery,只需要提供TRequest的类型:
1.3.4 静态成员
泛型类的静态成员需要特别关注。泛型类的静态成员只能在类的一个实例中共享。下面看一个例子,其中 StaticDemo<T>类包含静态字段x:
由于同时对一个string类型和一个int类型使用了StaticDemo<T>类,因此存在两组静态字段:
StaticDemo<string>.x = 4;
StaticDemo<int>.x = 5;
Console.WriteLine(StaticDemo<string>.x); // writes 4
1.4 泛型接口
使用泛型可以定义接口,接口中的方法可以带泛型参数。在链表示例中,就执行了IEnumerable<T>接口,它定义了GetEnumerator()方法,以返回IEnumerator<out T>。NET为不同的情况提供了许多泛型接口,例如,IComparable<T>、ICollection<T>和IExtensibleObject<T>。同一个接口常常存在比较老的非泛型版本,例如,.NET1.0有基于对象的IComparable接口。IComparable<inT>基于一个泛型类型:
比较老的非泛型接口IComparable需要一个带CompareTo0方法的对象。这需要强制转换为特定的类型,例如,Person类要使用LastName属性,就需要使用CompareToO方法:
执行泛型版本时,不再需要将object的类型强制转换为Person:
1.4.1 协变和抗变
在NET4之前,泛型接口是不变的。.NET4通过协变和抗变为泛型接口和泛型委托添加了一个重要的扩展。协变和抗变指对参数和返回值的类型进行转换.例如,可以给一个需要Shape参数的方法传送Rectangle参数吗?下面用示例说明这些扩展的优点。
在.NET中,参数类型是抗变的,假定有Shape和Rectangle类,Rectangle类派生自Shape基类。声明DisplayO方法是为了接受Shape类型的对象作为其参数:
现在可以传递派生自Shape基类的任意对象。因为Rectangle派生自Shape,所以Rectangle满足Shape的所有要求,编译器接受这个方法调用:
方法的返回类型是协变的。当方法返回一个Shape时,不能把它赋予Rectangle,因为Shape不一定总是 Rectangle。反过来是可行的:如果一个方法像GetRectangleO方法那样返回一个Rectangle,.
在NET Framework4版本之前,这种行为方式不适用于泛型。自C#4以后,扩展后的语言支持泛型接口和泛型委托的协变和抗变。下面开始定义Shape基类和Rectangle类.
1.4.2 泛型接口的协变
如果泛型类型用out关键字标注,泛型接口就是协变的。这也意味着返回类型只能是T。接口IIndex与类型T是协变的,并从一个只读索引器中返回这个类型.
IIndex<T>接口用RectangleCollection类来实现。RectangleCollection类为泛型类型T定义了Rectangle:
RectangleCollection.GetRectangleO方法返回一个实现IIndex<Rectangle>接口的RectangleCollection类,所以可以把返回值赋予IIndex<Rectangle>类型的变量rectangle。因为接口是协变的,所以也可以把返回值赋予 Index<Shape>类型的变量。Shape不需要Rectangle没有提供的内容。使用shapes变量,就可以在for循环中使用接口中的索引器和Cont属性。
1.4.3 泛型接口的抗变
如果泛型类型用关键字标注,泛型接口就是抗变的。这样,接口只能把泛型类型T用作其方法的输入。
ShapeDisplay类实现Display<Shape>,并使用Shape对象作为输入参数
创建ShapeDisplay的一个新实例,会返回Display<Shape>,并把它赋予shapeDisplay变量.因为Display<T>是抗变的,所以可以把结果赋予Display<Rectangle>,其中Rectangle派生自Shape。这次接口的方法只能把泛型类型定义为输入,而Rectangle满足Shape的所有要求。
1.5 泛型结构
与类相似,结构也可以是泛型的。它们非常类似于泛型类,只是没有继承特性。本节介绍泛型结构 Nullable<-T>,它由.NET Framework定义。
NET Framework中的一个泛型结构是Nullable<T>。数据库中的数字和编程语言中的数字有显著不同的特征,因为数据库中的数字可以为空,而C#中的数字不能为空。32是一个结构,而结构实现同值类型,所以结构不能为空。这种区别常常令人很头痛,映射数据也要多做许多辅助工作。这个问题不仅存在于数据库中,也存在于把XML数据映射到.NET类型。
一种解决方案是把数据库和L文件中的数字映射为引用类型,因为引用类型可以为空值。但这也会在运行期间带来额外的系统开销。
使用Nullable<T>结构很容易解决这个问题。下面的代码段说明了如何定义Nullable<T>的一个简化版本。结构Nullable<T>定义了一个约束:其中的泛型类型T必须是一个结构。把类定义为泛型类型后,就没有低系统开销这个优点了,而且因为类的对象可以为空,所以对类使用Nullable<T>类型是没有意义的。除了Nullable<T>定义的T类型之外,唯一的系统开销是has Value布尔字段,它确定是设置对应的值,还是使之为空。除此之外,泛型结构还定义了只读属性Has Value和Vaue,以及一些运算符重载。把Nullable<T>类型强制转换为T类型的运算符重载是显式定义的,因为当has Value为false时,它会抛出一个异常。强制转换为Nullable<T>类型的运算符重载定义为隐式的,因为它总是能成功地转换:
在这个例子中,Nullable<T>用Nullable<int>实例化。变量x现在可以用作一个int,进行赋值或使用运算符执行一些计算。这是因为强制转换了Nullable<T>类型的运算符。但是,x还可以为空。Nullable<T>的Has Value和Value属性可以检查是否有一个值,该值是否可以访问:
因为可空类型使用得非常频繁,所以C#有一种特殊的语法,它用于定义可空类型的变量。定义这类变量时不使用泛型结构的语法,而使用“?”运算符。在下面的例子中,变量x1和x2都是可空的t类型的实例:
可空类型可以与null和数字比较,如上所示。这里,x的值与null比较,如果x不是null,它就与小于0的值比较:
知道了Nullable<T>是如何定义的之后,下面就使用可空类型。可空类型还可以与算术运算符一起使用。变量x3是变量x1和x2的和。如果这两个可空变量中任何一个的值是null,它们的和就是null。
注意:这里调用的GetNullableType()方法只是一个占位符,它对于任何方法都返回一个可空的int。为了进行测试,简单起见,可以使实现的GetNullableTypeO返回null或返回任意整数。
非可空类型可以转换为可空类型。从非可空类型转换为可空类型时,在不需要强制类型转换的地方可以进行隐式转换。这种转换总是成功的:
但从可空类型转换为非可空类型可能会失败。如果可空类型的值是null,并且把null值赋予非可空类型就会抛出nvalidOperationException类型的异常。这就是需要类型强制转换运算符进行显式转换的原因:
如果不进行显式类型转换,还可以使用合并运算符从可空类型转换为非可空类型。合并运算符的语法是“?”,为转换定义了一个默认值,以防可空类型的值是null。这里,如果x1是null,y1的值就是0。
1.6 泛型方法
除了定义泛型类之外,还可以定义泛型方法。在泛型方法中,泛型类型用方法声明来定义。
Swap<T>方法把T定义为泛型类型,用于两个参数和一个变量temp:
把泛型类型赋予方法调用,就可以调用泛型方法:
但是,因为C#编译器会通过调用Swap方法来获取参数的类型,所以不需要把泛型类型赋予方法调用。泛型方法可以像非泛型方法那样调用:
1.6.1 带委托的泛型方法
这个Accumulate(0方法使用两个泛型参数T1和T2,第一个参数T1用于实现Enumerable<T1>参数的集合,第二个参数使用泛型委托FncT1,T2,TResult>。其中,第2个和第3个泛型参数都是T2类型。需要传递的方法有两个输入参数(T1和T2)和一个T2类型的返回值。
在调用这个方法时,需要指定泛型参数类型,因为编译器不能自动推断出该类型。对于方法的第1个参数,所赋予的accounts集合是Enumerable<Account>类型。对于第2个参数,使用一个lambda表达式来定义Account和decimal类型的两个参数,返回一个小数。对于每一项,通过Accumulate02方法调用这个lambda表达式。
不要为这种语法伤脑筋。该示例仅说明了扩展Accumulate()方法的可能方式。
相关文章:

C#高级编程笔记-泛型
本章的主要内容如下: ● 泛型概述 ● 创建泛型类 ● 泛型类的特性 ● 泛型接口 ● 泛型结构 ● 泛型方法 目录 1.1 泛型概述 1.1.1 性能 1.1.2 类型安全 1.1.3 二进制代码的重用 1.1.4 代码的扩展 1.1.5 命名…...

(超简单)SpringBoot中简单用工厂模式来实现
简单讲述业务需求 业务需要根据不同的类型返回不同的用户列表,比如按角色查询用户列表、按机构查询用户列表,用户信息需要从数据库中查询,因为不同的类型查询的逻辑不相同,因此简单用工厂模式来设计一下; 首先新建一个…...

java中的条件、循环和scanner类
if else ; 单行逻辑大括号可以省略;但是不建议省略; public static void main(String[] args) {boolean bool1 (Math.random() * 1000) % 2 > 1;System.out.println((Math.random() * 1000) % 2 "-" bool1);if(bool1) {System.out.prin…...

【Qt QML】Frame组件
Frame(框架)包含在: import QtQuick.Controls继承自Pane控件。用于在可视框架内布局一组逻辑控件。简单来说就是用来包裹和突出显示其他可视元素。Frame不提供自己的布局,但需要自己对元素位置进行设置和定位,例如通过…...

Web API之DOM
DOM 一.认识DOM二.获取元素三.事件基础四.操作元素(1).改变元素内容(2).修改元素属性(str、herf、id、alt、title)(3).修改表单属性(4).修改样式属性操作(5).小结 五.一些思想(1).排他思想(2).自定义属性的操作 六.节点操作1.认识2.节点层级关系3.创建和添加、删除、…...

windows驱动开发-内核编程技术汇总(六)
在驱动程序中使用文件 内核模式组件通过其对象名称引用文件,该对象名称是连接到文件的完整路径的 \DosDevices 。 在 Microsoft Windows 2000 及更高版本的操作系统上, \?? 等效于 \DosDevices。例如,C:\WINDOWS\example.txt 文件的对象名…...

Windows Server 2019虚拟机安装
目录 第一步、准备工作 第二步、部署虚拟机 第三步、 Windows Server 2019系统启动配置 第一步、准备工作 下载Windows Server 2019系统镜像 官网下载地址:Windows Server 2019 | Microsoft Evaluation Center VMware Workstation 17下载地址: 链…...

【软件工程】详细设计
目录 前言详细设计算法设计工具——判定表 前言 软件工程生命周期分为八个阶段: 问题定义—>可行性研究—>需求分析 —>概要设计—>详细设计—>编码与单元测试 —>综合测试—>软件维护 这节我们讲的是软件开发流程中的一个阶段,需求…...

在K8S中,集群可以做哪些优化?
在Kubernetes(简称K8s)集群中,可以进行多种优化以提升性能、稳定性和资源利用率。以下是一些常见的优化措施: 控制面组件优化: kube-apiserver 高可用与扩展:通过配置多个API服务器实例并使用负载均衡器分发…...

【C++】从零开始认识多态
送给大家一句话: 一个犹豫不决的灵魂,奋起抗击无穷的忧患,而内心又矛盾重重,真实生活就是如此。 – 詹姆斯・乔伊斯 《尤利西斯》 _φ(* ̄ω ̄)ノ_φ(* ̄ω ̄)&…...

为什么叫“机器学习”Machine Learning 而不是“计算机学习”——深度学习Note
有一门学科“机器学习”火了起来,它是计算机科学与数学结合的产物,它的目的是使计算机“聪明”起来,实现人工智能。可是,令人困惑的是它明明就是计算机学习,为什么不叫“计算机学习”而叫“机器学习”呢?这…...

Spring Boot集成RabbitMQ-之6大模式总结
A.集成 一:添加依赖 在pom.xml文件中添加spring-boot-starter-amqp依赖,以便使用Spring Boot提供的RabbitMQ支持: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp&…...

后端开发面经系列 -- 滴滴C++一面面经
滴滴C一面面经 公众号:阿Q技术站 来源:https://www.nowcoder.com/feed/main/detail/38cf9704ef084e27903d2204352835ef 1、const在C和C区别,const定义的类成员变量如何初始化? 区别 C中的const: 在C中,c…...

Three.js的几何形状
在创建物体的时候,需要传入两个参数,一个是几何形状【Geometry】,一个是材质【Material】 几何形状主要是存储一个物体的顶点信息,在Three中可以通过指定一些特征来创建几何形状,比如使用半径来创建一个球体。 立方体…...

设计模式——单例模式(Singleton)
单例模式(Singleton Pattern)是设计模式中的一种,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。这种模式在多种场景下都非常有用,比如配置文件的读取、数据库连接的创建、线程池的管理等。 实现…...

springboot3项目练习详细步骤(第二部分:文章分类模块)
新增文章分类 接口文档 业务实现 参数校验 文章分类列表 接口文档 业务实现 获取文章分类详情 接口文档 业务实现 更新文章分类 接口文档 业务实现 分组校验 问题 概念 实现步骤 总结 删除文章分类 接口文档 业务实现 该模块大部分请求的路径相同&…...

VUE中父组件向子组件进行传值
在 Vue 中,父组件向子组件传值主要通过在子组件的标签上绑定属性(props)的方式来实现。以下是一个具体的示例。 父组件(ParentComponent.vue): <template><div><!-- 父组件中使用子组件,并传…...

alpine安装中文字体
背景 最近在alpine容器中需要用到中文字体处理视频,不想从本地拷贝字体文件, 所以找到了一个中文的字体包font-droid-nonlatin,在此记录下。 安装 apk add font-droid-nonlatin安装好后会出现在目录下/usr/share/fonts/droid-nonlatin/ 这…...

JavaScript学习—JavaScript高级
原型链和继承 在 JavaScript 中,每个对象都有一个原型(prototype),这个原型指向另一个对象。这个链式的原型关系被称为原型链。当访问一个对象的属性时,如果该对象没有该属性,它会沿着原型链向上查找&…...

CompletableFuture使用案例
优化代码时,除了Async注解,项目中如何使用多线程异步调用? 举个例子,去餐厅吃饭的时候。先点餐,厨师做菜,在厨师做菜的时候打游戏,然后根据厨师做的菜的口味去买矿泉水还是可乐。这样࿰…...

安卓使用so库
最近需要给小伙伴扫盲一下如何使用Android Studio 生成一个SO文件,网上找了很多都没有合适的样例,那只能自己来写一个了。 原先生成SO是一个很麻烦的事情,现在Android Studio帮忙做了很多的事情,基本只要管好自己的C代码即可。 …...

【介绍下LeetCode的使用方法】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

重学java 30.API 1.String字符串
于是,虚度的光阴换来了模糊 —— 24.5.8 一、String基础知识以及创建 1.String介绍 1.概述 String类代表字符串 2.特点 a.Java程序中的所有字符串字面值(如“abc”)都作为此类的实例(对象)实现 凡是带双引号的,都是String的对象 String s "abc&q…...

【区块链】共识算法简介
共识算法简介 区块链三要素: 去中心化共识算法智能合约 共识算法作为区块链三大核心技术之一,其重要性不言而喻。今天就来简单介绍共识算法的基本知识。 最简单的解释,共识算法就是要让所有节点达成共识,保证少数服从多数&#x…...

Qt---day2-信号与槽
1、思维导图 2、 拖拽式 源文件 #include "mywidget.h" #include "ui_mywidget.h" MyWidget::MyWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::MyWidget) { ui->setupUi(this); //按钮2 this->btn2new QPushButton("按钮2",th…...

Python中设计注册登录代码
import hashlib import json import os import sys # user interface 用户是界面 UI """ 用户登录系统 1.注册 2.登陆 0.退出 """ # 读取users.bin def load(path): return json.load(open(path, "rt")) # 保存user.bin def save(dic…...

AI伦理和安全风险管理终极指南
人工智能(AI)正在迅速改变各个领域的软件开发和部署。驱动这一转变的两个关键群体为人工智能开发者和人工智能集成商。开发人员处于创建基础人工智能技术的最前沿,包括生成式人工智能(GenAI)模型、自然语言处理&#x…...

golang testing使用
testing包服务于自动化测试 基本测试 Table Drvien Test 基于表的测试通过表形式进行测试每种情况的输入和期望输出,从而测试程序的正确性 func TestFib(t *testing.T) {var fibTests []struct {in int // inputexpected int // expected result}{{1, 1}…...

在Excel中使用正则提取单元格内容
在办公自动化的浪潮中,Excel 作为数据处理的利器,一直在不断进化。最近,我注意到了不坑盒子Office插件一个非常实用的功能更新——bk_regex_string 公式。这个功能对于我们这些日常需要处理大量文本和数据的办公人员来说,无疑是一…...

SQL查询语句(二)逻辑运算关键字
上一篇文章中我们提到了条件查询除了一些简单的数学符号之外,还有一些用于条件判断的关键字,如逻辑判断 关键字AND,OR,NOT和范围查找关键字BETWEEN,IN等;下面我们来介绍一些这些关键字的用法以及他们所表达的含义。 目录 逻辑运算关键字 AND…...