C#学习总结

更新时间:2024-01-20 18:22:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

关键字:#region 定义可扩展和收缩的代码的开头

关键字:#endregion定义可扩展和收缩的代码的结尾

变量的命名:第一个字符必须是字母、下划线或@(区别于C)

Hungarian记号法:变量名前加小写,如iAge PascalCase:每个单词首字母大写 命名空间的两种约定 (第一个字母大写) (.Net Framework) 建议:简单高级

CamelCase:第一个单次首字母小写

(下划线字符变量名以及淘汰)

Console.ReadLine() 提示用户输入信息,区别于java中的System.out,print();

Console.WriteLine() 将结果打印出来,区别于java中的System.out,println();

Convert.toduble() 把字符串转换为double类型;

Using语句可以应用到包含它们的命名空间;

C# 与 C++在switch语句中的一个主要区别是,在C++中,可以在运行完一个case语句后,运行另一个case语句,而C#不行,会通过break语句中断(但出现多个case语句堆叠,其后出现一行代码,实际上就是一次检查多个条件);

关键字:const声明常量

Xxx.ToLower() 把输入的字符或字符串转换成小写

问题console.write() 与console.writeline() 的区别?

解答:每次输入一个字符时,console.write()不需要从一个新行开始,而console.writeline()就会从新的一行开始,也就是看输出是否需要换行而决定使用哪一个。

Break, continue, goto, return在处理控制循环时的区别: Break——立即终止循环

continue—— 立即终止当前循环,继续执行下一次循环 goto——跳出循环,到标记的位置 return——跳出循环及其包含的参数

关键字checked 问题

溢出检查环境(什么区别)详见p76

关键字Unchecked 注:使用convert转换时,他总是要进行溢出检查,checked和unchecked关键字以及项目属性设置没有什么作用。

关键字:enum定义枚举,枚举使用一个基本类型来存储,默认为int,,每个值都会根据定义的顺序从0开始,每次加1,自动赋给对应的基本类型值;详见p81

for循环

使用区别(数组的数组应用foreach,详见p93)

foreach循环

.ToLower() 将字符串转换成小写 .ToUpper() 将字符串转换成大写

.ToCharArray() 获得一个可写的char数组

.length 获得数组的个数或字符串长度

.TrimStart()命令:把字符串前面的空格删掉 .TrimEnd() 命令:把字符串前面的空格删掉 注:.Trim() 命令:删掉字符串中的空格

.PadLeft() 命令:在字符串左边添加空格,使字符串达到指定的长度

.PadRight()命令:在字符串右边添加空格,使字符串达到指定的长度

.Split() 命令:把string转换为string数组,把它在制定的位置分隔开,这些位置采用char数组的形式

关键字:params参数,某函数可以使用params关键字来定义

关键字:ref 关键字:out,指定所给的参数是一个输出参数,

问题注:总结ref和out的使用说明以及在使用时的异同,详见p110

在运行期间把文本写入output窗口,只需调用下面的替代console.writeine()调用,就可以把文本写到希望的地方 Trace.WriteLine()没什么限制,可用于发布程序

问题使用这两个函数的好处

Debug.WriteLine() 仅在调试模式下运行,甚至不能编译为可发布的程序,一旦使用该命令就会消失

注:这两个函数的用法与console.writeine()的不同,其唯一的字符串参数用于输出消息,而不需要使用{x}语法插入变量值

.CopyTo() 把A中的值复制到B中(数组)

Debug模式Debug.Write() Console.Write() Release模式Trace.Write() Debug.WriteLineIf() Trace.WriteLineIf()跟踪点 Debug.Writeif() Trace.WriteIf()

Debug.Assert()带三个参数,布尔值、字符串 判定函数

Trace.Assert()带三个参数,布尔值、字符串

问题System.IndexOutOfRangeException详见P143 重点结构化异常处理语法:try……catch……finally 注:重点了解其语法以及熟练使用

关键字:throw 产生一个异常,需要把新初始化的异常作为其参数,产生一个异常,需要使用使用命名空间System的另一个异常System.Expection

例如throw(new System.Expection);

问题使用Trace.WriteLine() 要优于使用Debug.WriteLine(),因为调试版本仅能用于调试程序,这个观点正确与否,怎么解释? OPP技术

构造阶段—构造函数 对象的生命周期

析构阶段—析构函数(一般情况下,我们不依

赖析构函数释放对象实例使用的资源)

关键字:readonly表示这个字段只能在执行构造函数的过程中使用,或由初始化赋值语句赋值 public 关键字private 成员定义internal protected 定义字段

virtual-----方法可以重写

关键字abstract-----必须在非抽象的派生类中重写(抽象类) 定义方法override-----重写了一个基类方法 external-----定义放在其他地方

get关键字/函数 (访问器) 定义属性

重制成员:使用工具修改代码,而不是手工修改,如将public string mystring----->private string mystring set关键字/函数------->value关键字赋值

关键字:base 表示包含在派生类中的基类的执行代码,类似于构造函数的控制(1,要对派生类的用户隐藏继承的公共成员,但任然能够在类中访问其功能;2,要给继承的虚拟成员添加执行代码,而不是简单是的重写的新执行代码替代它)

关键字:this 与base一样,this也可用在类成员的内部,且该关键字也引用对象实例,即是当前实例,this关键字最常见的功能就是把当期对象实例的引用传递给一个方法

循环冗余码校验( CRC 校验):

循环冗余码校验是目前一种最常用的,也是最有效的差错检测编码。对一个 k 比特的数据块(或称报文),发送方生成一个 n比特的序列,称为帧检验序列( FCS),这个序列与原 k 比特的数据块组成一个长度为k+n比特的新序列(帧),如图 10-2-2,一起发送。当接收方收到这个k+n比特的帧后,进行校验。 这个特定的多项式称“生成多项式”。发送方采用数据报文整除生成多项式,得到帧检验序列,附加到发送数据报文之后。这个过程称为“生成”。

接收方,对接收到的报文用同样的生成多项式,再次进行整除,这个过程称为“校验”。若除后余数为 0(即能整除),表示接收的数据块正确,否则,表示接收数据有错。上述 CRC 校验只能发现错误,而不能纠正错误。

CRC 校验能够: 1)检查出全部一位错;

2)能检查出全部离散的二位错; 3)能检查出全部奇数个数错;

4)能检查出全部长度小于或等于 n 位的突发错( n 为生成多项式的阶次);

5)能以 1-( 1/2)^(n-1)的概率检查出长度为n+1 位的突发错。 例如,如果 k=16,则该 CRC 校验码能全部检查出小于或等于 16 位长度的突发错,

并能以 1-( 1/2)^( n-1)=99. 997%的概率检查出长度为 17 位的突发错,漏检概率为 0.0003%。

因此 CRC 校验的校验效率很高,是现代通信技术中使用最多的方法。要达到上述校验效率,生成多项式是关键。常用的生成多项式有:

CRC-12 P(x) =x^12+x^11+x^3+x^2+x^1+x^0 CRC-16 P(x) =x^16+x^15+x^2+x^0 CRC-CCITT P(x)=x^16+x^12+x^5+x^0 CRC-32

P(x)=x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+

x^4+x^2+x^1+x^0

CRC 校验可用硬件电路实现,其逻辑如图 10-2-3 所示,其中相加点为异或逻辑,方框为移位寄存器,位数与帧检验序列相同。CRC 校验也可比照图 10-2-3,采用软件实现。其中多项式整除采用按位除(不带进位)。即运算过程采用异或、移位操作完成。用程序实现 CRC校验序列的生成和 CRC 校验的过程如下:

CRC 校验序列生成:

1.首先在数据报文后添入与帧检验序列位数相同个 0。从数据序列头部开始,与生成多项式进行异或运算。

2.根据数据序列最高位的状态,若为 1,进行异或运算;若为 0,不进行异或运算。然后将整个数据报文(连同添加的 0 一起)左移一位,移出的数据自动丢失。

3.对剩余的报文继续执行第 2 步运算和左移过程,直到添加的 0 也经异或运算完成。产生的余数即为生成的 CRC 校验码序列。将它作为报文的添加字节,一起发送。CRC 校验的计算方法与生成过程中第 2、 3 步相同,直到报文最后一位(连同发送端添加 CRC校验码序列在内),若结果余数为 0,表示正确,否则接收到的报文有错。 例 10-2-1 CRC 校验过程

假定发送数据序列为: 1010001101, CRC生成多项式为: P(x)=x^5+x^4+x^2+1=110101

发送数据序列*25: 101000110100000 运算:

101000 110100000

⊕110101 ;最高位为 1,进行异或运算

011101 110100000

0 111011 10100000 ;左移一位,首位 0(斜体丢弃) ⊕ 110101 ;最高位为仍 1,进行异或运算 001110 10100000

0 0111010 100000 ;左移一位,首位 0(斜体丢弃)。 ;最高位为 0,不进行异或运算, 0 111010 100000 ;继续左移一位 ⊕110101 ;最高位为 1,进行异或运算 001111 100000

00 111110 0000 ;左移一位,首位 0(斜体丢弃),再左移一位,首位 0(斜体丢弃) ⊕ 110101

001011 0000 ;同上连续左移二位 00 101100 00 ⊕ 110101

011001 00 0 110010 0 ⊕ 110101 000111 0 0 001110

将余数 01110 附在原数据序列中,得发送数据序列 101000110101110 接收校验过程:

101000110101110 101100110101110 ⊕110101 ⊕ 110101 0111011 0110011 ⊕ 110101 ⊕110101 00111010 000110101 ⊕ 110101 ⊕ 110101 0011111000000001110 ⊕ 110101 有差错 00101111 ⊕ 110101 0110101 ⊕ 110101 000000 没有差错

关键字:base 表示包含在派生类中得基类的执行代码(在控制构造函数时,用法相似)

接口成员的定义与类成员的定义的异同:

(1) 不允许使用访问修饰符(如publiu、internal等),所

有的接口成员都是公共的;

(2) 接口成员不能包含代码体什么意思? (3) 接口不能定义字段成员;

(4) 接口成员不能用关键字static、virtual、abstract、sealed

来定义;

(5) 类型定义的成员是禁止的。

关键字: new 可以隐藏继承了基接口的成员,其执行方式与隐藏继承的类成员一样,在接口中的定义的属性可以确定访问块get和、或set中的哪一个不能用于该属性。

部分类的定义:代码采用可以扩展和压缩的字段、属性、构造函数和方法,以便集中精力考虑自己感兴趣的内容;如采用#region 。。。。。。。。#endregion(partial class definition),应用于部分类的接口也会应用于整个类,因此每个部分类定义的文件中对类使用关键字partial;

扑克牌示例应用程序的步骤: 只读字段suit的容器 一、规划应程序Card类

类库(Lib)只读字段suit的容器 Deck类:包含的若干对象,以及方法

添加Suit和Rank枚举>枚举成员

二、编写类库添加Card类>字段、方法、构造函数 (.cs)

添加Deck类>字段、方法、构造函数 三、类库的客户应用程序------>>添加类库项目

使用集合 定义集合

索引符------->>特殊类型的属性 给xxxLib添加???集合 集合关键字值集合和IDictionary 迭代器 深度复制

给xxxLib添加深度复制

C#中的数组实现为System.Array类的实例,他只是集合类的一种,集合类一般用于处理对象列表,其功能比简单数组要多,这些功能是通过实现System.Collections命名空间中的接口而获得的,因此集合的的语法已经标准化。

关键字:yield(查资料了解其用法)

封箱和装箱 类型比较 is运算符 比较运算符重载

值比较给xxxLib添加运算符重载 IComparable和IComparer接口

显式转换:explicit关键字 重载转换运算符

转换隐式转换: implicit 关键字 把一种类型转换为指定的引用类型 as运算符 as 同类型、隐式转换、封箱

值类型:大多数基本类型,例如int、double和所有的结构

引用类型:string和所有的类

注:值类型必须包含一个值,它可以在声明之后、赋值之前,在未赋值的状态下存在,但不能以任何方式使用。而引用类型可以是null。

可空类型(nullable type):解决值类型的一个小问题 System.NullablenullableInt------>声明一个变量nullableInt nullableInt = null 不能编译,应该这样: nullableInt = new System.Nullable(); 可空类型的测试:

If(nullableInt == null) {……..} 等价于 f(nullableInt.HasValue) {……..}

注:上述测试方法不适用于引用类型,因为引用类型的变量值为null时就表示不存在对象,即使引用类型有一个HasValue属性。

可空类型的简化缩写:int? nullableInt; 如:int? op1 = 5;

Int? result = op1 * 2;(int result = op1 * 2会出现错误) ??运算符:int? op1 = null; (把5值赋给result)

Int result = op1 * 2 ?? 5; (??自动转换类型)

∷运算符:提供了访问命名空间中类型的另一种方式,即给出的命名空间别名优于一般的类型限定。与global关键字一起使用,它实际上是顶级根命名空间的别名。

多态性:多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为\一个接口,多个功能\。多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。

静态多态性:在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:

(1)函数重载您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。

(2)运算符重载可以重定义或重载 C# 中内置的运算符。因此,程序员也可以使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回

类型和参数列表 。

动态多态性:C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。 注:下面是有关抽象类的一些规则: 您不能创建一个抽象类的实例。

您不能在一个抽象类外部声明一个抽象方法。

通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。

当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。

动态多态性是通过 抽象类 和 虚方法 实现的。

接口(Interface):接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 \是什么\部分,派生类定义了语法合同 \怎么做\部分。

(1)接口定义了属性、方法和事件,这些都是接口的成员。

(2)接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。

(3)抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时。 (4)接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的。

反射(Reflection):反射指程序可以访问、检测和修改它本身状态或行为的一种能力。程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。 优缺点之优点:

1、反射提高了程序的灵活性和扩展性。 2、降低耦合性,提高自适应能力。

3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。 优缺点之缺点:

1、性能问题:使用发射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此发射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议

使用。

2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。 反射(Reflection)的用途:

1、它允许在运行时查看属性(attribute)信息。

2、它允许审查集合中的各种类型,以及实例化这些类型。 3、它允许延迟绑定的方法和属性(property)。

4、它允许在运行时创建新类型,然后使用这些类型执行一些任务。

属性(Property): 是类(class)、结构(structure)和接口(interface)的命名(named)成员。类或结构中的成员变量或方法称为 域(Field)。属性(Property)是域(Field)的扩展,且可使用相同的语法来访问。它们使用 访问器(accessors) 让私有域的值可被读写或操作。

注:属性(Property)不会确定存储位置。相反,它们具有可读写或计算它们值的 访问器(accessors)。

例如,有一个名为 Student 的类,带有 age、name 和 code 的私有域。我们不能在类的范围以外直接访问这些域,但是我们可以拥有访问这些私有域的属性。

访问器(Accessors):属性(Property)的访问器(accessor)

包含有助于获取(读取或计算)或设置(写入)属性的可执行语句。访问器(accessor)声明可包含一个 get 访问器、一个 set 访问器,或者同时包含二者。

索引器(Indexer): 允许一个对象可以像数组一样被索引。当您为类定义一个索引器时,该类的行为就会像一个 虚拟数组(virtual array) 一样。您可以使用数组访问运算符([ ])来访问该类的实例。

索引器(Indexer)的用途:索引器的行为的声明在某种程度上类似于属性(property)。就像属性(property),您可使用 get 和 set 访问器来定义索引器。但是,属性返回或设置一个特定的数据成员,而索引器返回或设置对象实例的一个特定值。换句话说,它把实例数据分为更小的部分,并索引每个部分,获取或设置每个部分。

定义一个属性(property)包括提供属性名称。索引器定义的时候不带有名称,但带有 this 关键字,它指向对象实例。 重载索引器(Indexer):索引器(Indexer)可被重载。索引器声明的时候也可带有多个参数,且每个参数可以是不同的类型。没有必要让索引器必须是整型的。C# 允许索引器可以是其他类型。

委托(Delegate):C# 中的委托(Delegate)类似于 C 或 C++

中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。

注:委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。 声明委托(Delegate):委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。

实例化委托(Delegate):一旦声明了委托类型,委托对象必须使用 new 关键字来创建,且与一个特定的方法有关。当创建委托时,传递到 new 语句的参数就像方法调用一样书写,但是不带有参数。

委托的多播(Multicasting of a Delegate):委托对象可使用 \运算符进行合并。一个合并委托调用它所合并的两个委托。只有相同类型的委托可被合并。\运算符可用于从合并的委托中移除组件委托。使用委托的这个有用的特点,您可以创建一个委托被调用时要调用的方法的调用列表。这被称为委托的 多播(multicasting),也叫组播。下面的程序演示了委托的多播:

usingSystem; delegateintNumberChanger(int n); namespaceDelegateAppl { classTestDelegate { staticintnum=10; publicstaticintAddNum(int p) { num+= p; returnnum; }

publicstaticintMultNum(int q) {

num*= q; returnnum; }

publicstaticintgetNum() {

returnnum; }

staticvoidMain(string[]args) {

// 创建委托实例 NumberChangernc;

NumberChanger nc1 =newNumberChanger(AddNum); NumberChanger nc2 =newNumberChanger(MultNum); nc= nc1; nc+= nc2; // 调用多播 nc(5);

Console.WriteLine(\,getNum()); Console.ReadKey(); } } }

当上面的代码被编译和执行时,它会产生下列结果:Value of Num: 75

事件(Event): 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些出现,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。事件是用于进程间通信。

通过事件使用委托:事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。 发布器(publisher): 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。 订阅器(subscriber): 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。 声明事件(Event):在类的内部声明事件,首先必须声明该事件的委托类型。例如: publicdelegatevoidBoilerLogHandler(string status); 然后,声明事件本身,使用 event 关键字: // 基于上面的委托定义事件 publiceventBoilerLogHandlerBoilerEventLog; 上面的代码定义了一个名为 BoilerLogHandler 的委托和一个名为 BoilerEventLog 的事件,该事件在生成的时候会调用委托。

本实例提供一个简单的用于热水锅炉系统故障排除的应用程序。当维修工程师检查锅炉时,锅炉的温度和压力会随着维修工程师的备注自动记录到日志文件中。

usingSystem; usingSystem.IO;

namespaceBoilerEventAppl {

// boiler 类 classBoiler {

privateint temp; privateint pressure; publicBoiler(int t,int p) {

temp= t; pressure= p; }

publicintgetTemp() {

return temp; }

publicintgetPressure() {

return pressure; } }

// 事件发布器

classDelegateBoilerEvent {

publicdelegatevoidBoilerLogHandler(string status);

// 基于上面的委托定义事件

publiceventBoilerLogHandlerBoilerEventLog;

publicvoidLogProcess() {

string remarks =\; Boiler b =newBoiler(100,12);

int t =b.getTemp(); int p =b.getPressure();

if(t >150|| t <80|| p <12|| p >15) {

remarks=\; }

OnBoilerEventLog(\);

OnBoilerEventLog(\+ t +\+ p); OnBoilerEventLog(\+ remarks); }

protectedvoidOnBoilerEventLog(string message) {

if(BoilerEventLog!=null) {

BoilerEventLog(message); } } }

// 该类保留写入日志文件的条款 classBoilerInfoLogger {

FileStream fs; StreamWritersw;

publicBoilerInfoLogger(string filename) {

fs=newFileStream(filename,FileMode.Append,FileAccess.Write); sw=newStreamWriter(fs); }

publicvoidLogger(string info) {

sw.WriteLine(info); }

publicvoidClose() {

sw.Close(); fs.Close(); } }

// 事件订阅器

publicclassRecordBoilerInfo {

staticvoidLogger(string info) {

Console.WriteLine(info); }//end of Logger staticvoidMain(string[]args) { BoilerInfoLoggerfilelog=newBoilerInfoLogger(\); DelegateBoilerEventboilerEvent=newDelegateBoilerEvent(); boilerEvent.BoilerEventLog+=new DelegateBoilerEvent.BoilerLogHandler(Logger); boilerEvent.BoilerEventLog+=new DelegateBoilerEvent.BoilerLogHandler(filelog.Logger); boilerEvent.LogProcess(); Console.ReadLine(); filelog.Close(); }//end of main }//end of RecordBoilerInfo } 当上面的代码被编译和执行时,它会产生下列结果: Logging info: Temperature 100 Pressure 12 Message: O. K

泛型(Generic): 允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。

您可以通过数据类型的替代参数编写类或方法的规范。当编译器遇到类的构造函数或方法的函数调用时,它会生成代码来处理指定的数据类型。

泛型(Generic)的特性:使用泛型是一种增强程序功能的技术,具体表现在以下几个方面:

?

它有助于您最大限度地重用代码、保护类型的安全以及提高性能。

?

您可以创建泛型集合类。.NET 框架类库

在 System.Collections.Generic 命名空间中包含了一些新的泛型集合类。您可以使用这些泛型集合类来替代 System.Collections 中的集合类。

?

您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。

?

您可以对泛型类进行约束以访问特定数据类型的方法。 关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取。

?

泛型(Generic)委托:

可以通过类型参数定义泛型委托。例如: delegate T NumberChanger(T n); unsafe 修饰符: C# 允许在函数中使用指针变量。不安全代码或非托管代码是指使用了指针变量的代码块。指针 是值为另一个变量的地址的变量,即,内存位置的直接地址。就像其他变量或常量,您必须在使用指针存储其他变量地址之前声明指针。

关键字: fixed在 C# 中,数组名称和一个指向与数组数据具有相同数据类型的指针是不同的变量类型。例如,int *p 和int[] p 是不同的类型。您可以增加指针变量 p,因为它在内存中不是固定的,但是数组地址在内存中是固定的,所以您不能增加数组 p。

因此,如果您需要使用指针变量访问数组数据,可以像我们通常在 C 或 C++ 中所做的那样,使用 fixed 关键字来固定指针。

多线程:线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。

线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率。

到目前为止我们编写的程序是一个单线程作为应用程序的运行实例的单一的过程运行的。但是,这样子应用程序同时只能执行一个任务。为了同时执行多个任务,它可以被划分为更小的线程。

线程生命周期:开始于System.Threading.Thread类的对象被创建时,结束于线程被终止或完成执行时。 下面列出了线程生命周期中的各种状态:

*未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。

*就绪状态:当线程准备好运行并等待 CPU 周期时的状况。 *不可运行状态:下面的几种情况下线程是不可运行的:

已经调用 Sleep 方法 已经调用 Wait 方法 通过 I/O 操作阻塞

*死亡状态:当线程已完成执行或已中止时的状况。 主线程:在 C# 中,System.Threading.Thread 类用于线程的工作。它允许创建并访问多线程应用程序中的单个线程。进程中第一个被执行的线程称为主线程。

当 C# 程序开始执行时,主线程自动创建。用 Thread 类创建的线程被主线程的子线程调用。您可以使用 Thread 类的 CurrentThread属性访问线程。 过程为:创建线程—>管理线程—>销毁线程

MODBUS协议 委托

本文来源:https://www.bwwdw.com/article/klao.html

Top