C#高级编程笔记-泛型

news2024/11/25 10:34:16

本章的主要内容如下:

●       泛型概述

●       创建泛型类

●       泛型类的特性

●       泛型接口

●       泛型结构

●       泛型方法

目录

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()方法的可能方式。

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

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

相关文章

2024高校网络安全管理运维赛wp

文章目录 misc签到钓鱼邮件识别easyshellSecretDBGatewayzipApachef for r webphpsqlMessy Mongo misc 签到 钓鱼邮件识别 两部分解base64&#xff0c;各一个flag 后面没有什么地方有有用信息了&#xff0c;根据题目钓鱼邮件&#xff0c;可能第三段flag就跟DMARC、DKIM 和 SP…

LED显示屏的维护与使用指南

LED显示屏作为一种先进的显示技术&#xff0c;广泛应用于广告、信息显示、舞台背景等领域。然而&#xff0c;为了确保显示屏的长期稳定运行和良好的显示效果&#xff0c;对其进行正确的维护和使用是非常必要的。以下是一些专业的维护与使用建议&#xff1a; 维护建议&#xff1…

个人IP打造孵化运营产业链商业计划书

【干货资料持续更新&#xff0c;以防走丢】 个人IP打造孵化运营产业链商业计划书 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PPT共90页&#xff08;完整资料包含以下内容&#xff09; 目录 个人IP运营方案&#xff1a; 1. 个人IP定位与构建 1.1 人格画像构…

Chromium编译指南2024 Windows11篇-Git工具准备(四)

前言 在《Chromium编译指南2024&#xff08;三&#xff09;》中&#xff0c;我们已经完成了对 Chromium 编译环境的其他相关环境变量的设置&#xff0c; 接下来&#xff0c;我们将进一步探讨如何初始化配置 Git&#xff0c;为获取 Chromium 源代码做好准备。 1. 配置Git 用户…

计算有效声压

计算有效声压 clear all; %%----------------------------------------------读取文件------------------------------------------ % 从wav文件读入语音数据&#xff0c;该语音采样率16k&#xff0c;故信号最高频率8k。 [x,fs]audioread(C2_3_y.wav); % 取x的一个通道 xx(:,1)…

校园论坛系统基于PHP的校园管理系统毕设校园好感度系统 校园文化建设系统APP小程序H5前后端源码交付支持二开,一次付款,终生使用

APP小程序H5前后端源码交付&#xff0c;支持二开&#xff0c;一次付款&#xff0c;终身使用&#xff0c;免费更新系统本身源码。 校园社交网络系统开发是一个复杂且综合性的项目&#xff0c;旨在为学生、教师和管理人员提供一个互动、分享和交流的平台。以下是一个关于校园社交…

Windows Server 2012R2定时计划任务设置

1.打开Windows定时计划任务 2.点击右侧“创建任务” 3.在弹出的“创建任务”对话框中,输入任务名称,设定运行任务时,使用的用户账户等信息;点击“触发器”选项 4.在“触发器”选项中,点击“新建”按钮,设置触发条件;根据实际情况,设置“开始任务”、设置“起止”时间…

记一次favicon.ico的折腾

某项目需要将前端和后台整合在一起 我也不知道为啥要整合 上面有要求就整呗 正常前端npm run build打包后 dist内会根据设置自动生成favicon.ico文件在根目录下 但由于前后端整合 需要打包后将图标放在dist下的static文件夹里 需要的效果 打包后 index.html里 <link rel&…

0507华为od二面

只记录自己没回答上的问题 1、ZGC的缺点&#xff1a; 1)只是适用于32位系统 2)最大只是支持4TB内存容量 3)最糟糕的情况下吞吐量会下降15%&#xff0c;这都不是事至于吞吐量&#xff0c;通过扩容分分钟解决 4)分代的原因:不同对象的生命周期不相同&#xff0c;可能会扫描整个堆…

CSS-伪类选择器

结构伪类选择器 作用&#xff1a;根据元素的结构关系查找元素 分类&#xff1a; 选择器说明元素名:first-child查找第一个元素元素名:last-child查找最后一个元素元素名:nth-child(N)查找第N名元素 <!DOCTYPE html> <html lang"en"> <head><me…

VMware 替代专题|14 个常见问题,解读 VMware 替代的方方面面

随着 VMware by Broadcom 调整订阅模式和产品组合&#xff0c;不少用户也将 VMware 替代提上日程。为了帮助用户顺利完成从 VMware 替代方案评估到产品落地的一系列环节&#xff0c;我们通过这篇博客&#xff0c;对 VMware 替代场景下用户经常遇到的问题进行了梳理和解答。 更…

【Ansiable】ansible的模块和主机清单

Ansible Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。 Ansible能批量配置、部署、管理上千台主机。比…

2024年全域电商矩阵109节线上课

《24年全域电商矩阵109节线上课》是一门全面介绍电子商务领域的课程。从电子商务的基本概念到全球电子商务趋势&#xff0c;再到电子商务的营销策略和实际操作技巧&#xff0c;本课程涵盖了丰富多样的主题。学员将通过109节在线课程系统全面了解电子商务&#xff0c;并获得在这…

MCU做死循环时,到底应该用for(;;) 还是wihile(1)

MCU做死循环时 for while stm32中老工程师用forfor while背景for版本while版本正方观点&#xff1a;哪有好的编译器&#xff1a;反方观点&#xff1a;这种代码过时了工程师实地测试&#xff1a;和编译器和优化有关 建议还是用for参考 stm32中老工程师用for /* Start scheduler …

牛客网刷题 | BC80 奇偶统计

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 任意输入一个正整数…

python 打包为exe可执行程序

近期因为需要做文字识别&#xff0c;应用ocr 所以每次都需要部署环境&#xff0c;然后打算做成exe&#xff0c;遇到问题做一总结。 pyinstaller -D --hidden-importpaddleocr testflask.py 生成exe paddleocr 和pyinstaller 安装不做说明。 No such file or directory: …

STM32接入CH340芯片的初始化进入升级模式(死机)问题处理

目录 1. 问题描述2. 问题分析2.1 CH340G/K 的初始化波形2.2 第1种USB升级电路2.3 第2种USB升级电路2.4 第3种USB升级电路2.5 第4种USB升级电路 3. 总结 1. 问题描述 我所用的CH340G&#xff08;CH340K也用过&#xff09;接在MCU的电路中&#xff0c;在插入CH340G/K 的接插件&a…

欢迎参展GASITC2024成都国际城市燃气智能应用技术展

GASITC2024中国&#xff08;成都&#xff09;国际城市燃气智能应用技术展览会 2024China City Gas Intelligent Application Technology Exhibition 同期召开&#xff1a;第十五届&#xff08;成都&#xff09;国际化工技术及装备展览会 展出地点&#xff1a;成都世纪城新国…

Vue CLI配置代理、2.0、3.0

一、vue cli2.0 代理配置 proxy: {/api:{target: "http://localhost:8067",pathRewrite: {/api: }}, } 一、vue cli3.0 代理配置 proxy: {/api: {target: http://localhost:8067,pathRewrite: {/api: }} }

OSPF链路状态数据库

原理概述 OSPF是一种基于链路状态的动态路由协议&#xff0c;每台OSPF路由器都会生成相关的LSA&#xff0c;并将这些LSA通告出去。路由器收到LSA后&#xff0c;会将它们存放在链路状态数据库LSDB中。 LSA有多种不同的类型&#xff0c;不同类型的LSA的功能和作用是不同的&…