C#笔记(39)多线程
多线程线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。 线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率。 到目前为止我们编写的程序是一个单线程作为应用程序的运行实例的单一的过程运行的。但是,这样子应用程序同时只能执行一个任务。为了同时执行多个任务,它可以被划分为更小的线程。 线程生命周期线程生命周期开始于 System.Threading.Thread 类的对象被创建时,结束于线程被终止或完成执行时。 下面列出了线程生命周期中的各种状态: 未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。 就绪状态:当线程准备好运行并等待 CPU 周期时的状况。 不可运行状态:下面的几种情况下线程是不可运行的: 已经调用 Sleep 方法 已经调用 Wait 方法 通过 I/O 操作阻塞 死亡状态:当线程已完成执行或已中止时的状况。 主线程在 C# ...
C#笔记(38)不安全代码
不安全代码当一个代码块使用 unsafe 修饰符标记时,C# 允许在函数中使用指针变量。不安全代码或非托管代码是指使用了指针变量的代码块。 指针变量指针 是值为另一个变量的地址的变量,即,内存位置的直接地址。就像其他变量或常量,您必须在使用指针存储其他变量地址之前声明指针。 指针变量声明的一般形式为: 1type* var-name; 下面是指针类型声明的实例: 实例 描述 int* p p 是指向整数的指针。 double* p p 是指向双精度数的指针。 float* p p 是指向浮点数的指针。 int** p p 是指向整数的指针的指针。 int*[] p p 是指向整数的指针的一维数组。 char* p p 是指向字符的指针。 void* p p 是指向未知类型的指针。 在同一个声明中声明多个指针时,星号 ***** 仅与基础类型一起写入;而不是用作每个指针名称的前缀。 例如: 12int* p1, p2, p3; // 正确 int *p1, *p2, *p3; // 错误 下面的实例说明了 C# 中使用了 ...
C#笔记(37)匿名方法
匿名方法我们已经提到过,委托是用于引用与其具有相同标签的方法。换句话说,您可以使用委托对象调用可由委托引用的方法。 匿名方法(Anonymous methods) 提供了一种传递代码块作为委托参数的技术。匿名方法是没有名称只有主体的方法。 在匿名方法中您不需要指定返回类型,它是从方法主体内的 return 语句推断的。 编写匿名方法的语法匿名方法是通过使用 delegate 关键字创建委托实例来声明的。例如: 123456delegate void NumberChanger(int n);...NumberChanger nc = delegate(int x){ Console.WriteLine("Anonymous Method: {0}", x);}; 代码块 Console.WriteLine(“Anonymous Method: {0}”, x); 是匿名方法的主体。 委托可以通过匿名方法调用,也可以通过命名方法调用,即,通过向委托对象传递方法参数。 注意: 匿名方法的主体后面需要一个 ;。 例如:...
C#笔记(36)泛型(Generic)
泛型(Generic)泛型(Generic) 允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。 您可以通过数据类型的替代参数编写类或方法的规范。当编译器遇到类的构造函数或方法的函数调用时,它会生成代码来处理指定的数据类型。下面这个简单的实例将有助于您理解这个概念: 实例1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556using System;using System.Collections.Generic;namespace GenericApplication{ public class MyGenericArray<T> { private T[] array; public MyGenericArray(int size) {...
C#笔记(35)集合(Collection)
集合(Collection)集合(Collection)类是专门用于数据存储和检索的类。这些类提供了对栈(stack)、队列(queue)、列表(list)和哈希表(hash table)的支持。大多数集合类实现了相同的接口。 集合(Collection)类服务于不同的目的,如为元素动态分配内存,基于索引访问列表项等等。这些类创建 Object 类的对象的集合。在 C# 中,Object 类是所有数据类型的基类。 什么是集合? 在 C# 中存储大量数据时,除了使用数组外,还可使用另外一种容器:集合。 相比数组不能修改长度的缺点,集合在进行操作时,对集合中的元素进行增删改查操作,作用都是原集合,而不会产生新的集合。 另外,有一些集合中还可以存储任意类型的数据。 ArrayListArrayList 介绍 底层就是一个可动态扩展的数组; 提供了用于在集合中添加、删除或查找项的方法; ArrayList 集合不支持泛型(即:可放任意类型的数据); 使用 ArrayList 集合之前,应先导入命名命名空间: using System.Collections ; 用于unity开发...
C#笔记(34)事件(Event)
事件(Event)事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。 C# 中使用事件机制实现线程间的通信。 通过事件使用委托事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。 发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。 订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。 声明事件(Event)在类的内部声明事件,首先必须声明该事件的委托类型。例如: 1public delegate void Boil...
C#笔记(33)委托(Delegate)
委托(Delegate)C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。 委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。 声明委托(Delegate)委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。 例如,假设有一个委托: 1public delegate int MyDelegate (string s); 上面的委托可被用于引用任何一个带有一个单一的 string 参数的方法,并返回一个 int 类型变量。 声明委托的语法如下: 1delegate <return type> <delegate-name> <parameter list> 实例化委托(Delegate)一旦声明了委托类型,委托对象必须使用 new 关键字来创建,且与一个特定的方法有关。当创建委托时,传递到 new 语句的参数就像方法调用一样书写,但是...
C#笔记(32)索引器(Indexer)
索引器(Indexer)索引器(Indexer) 允许一个对象可以像数组一样使用下标的方式来访问。 当您为类定义一个索引器时,该类的行为就会像一个 虚拟数组(virtual array) 一样。您可以使用数组访问运算符 [ ] 来访问该类的的成员。 语法一维索引器的语法如下: 1234567891011121314element-type this[int index]{ // get 访问器 get { // 返回 index 指定的值 } // set 访问器 set { // 设置 index 指定的值 }} 索引器(Indexer)的用途索引器的行为的声明在某种程度上类似于属性(property)。就像属性(property),您可使用 get 和 set 访问器来定义索引器。但是,属性返回或设置一个特定的数据成员,而索引器返回或设置对象实例的一个特定值。换句话说,它把实例数据分为更小的部分,并索引每个部分,获取或设置每个部分。 定义一个属性(property...
C#笔记(31)属性(Property)
属性(Property)属性(Property) 是类(class)、结构(structure)和接口(interface)的命名(named)成员。类或结构中的成员变量或方法称为 域(Field)。属性(Property)是域(Field)的扩展,且可使用相同的语法来访问。它们使用 访问器(accessors) 让私有域的值可被读写或操作。 属性(Property)不会确定存储位置。相反,它们具有可读写或计算它们值的 访问器(accessors)。 例如,有一个名为 Student 的类,带有 age、name 和 code 的私有域。我们不能在类的范围以外直接访问这些域,但是我们可以拥有访问这些私有域的属性。 访问器(Accessors)属性(Property)的**访问器(accessor)**包含有助于获取(读取或计算)或设置(写入)属性的可执行语句。访问器(accessor)声明可包含一个 get 访问器、一个 set 访问器,或者同时包含二者。例如: 12345678910111213141516171819202122232425262728293031323334...
C#笔记(30)反射(Reflection)
反射(Reflection)反射指程序可以访问、检测和修改它本身状态或行为的一种能力。 程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。 您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。 优缺点优点: 1、反射提高了程序的灵活性和扩展性。 2、降低耦合性,提高自适应能力。 3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。 缺点: 1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。 2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。 反射(Reflection)的用途反射(Reflection)有下列用途: 它允许在运行时查看特性(attribute)信息。 它允许审查集合中的各种类型,以及实例化这些类型。 它允许延迟绑定的方法和属性(...
C#笔记(29)特性(Attribute)
特性(Attribute)**特性(Attribute)**是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性。 规定特性(Attribute)规定特性(Attribute)的语法如下: 12[attribute(positional_parameters, name_parameter = value, ...)]element 特性(Attribute)的名称和值是在方括号内规定的,放置在它所应用的元素之前。positional_parameters 规定必需的信息,name_parameter 规定可选的信息。 预定义特性(Attribute).Net 框架提供了三种预定义特性: AttributeUsage Conditional Obsolete AttributeU...
C#笔记(28)文件的输入与输出
文件的输入与输出一个 文件 是一个存储在磁盘中带有指定名称和目录路径的数据集合。当打开文件进行读写时,它变成一个 流。 从根本上说,流是通过通信路径传递的字节序列。有两个主要的流:输入流 和 输出流。输入流用于从文件读取数据(读操作),输出流用于向文件写入数据(写操作)。 C# I/O 类System.IO 命名空间有各种不同的类,用于执行各种文件操作,如创建和删除文件、读取或写入文件,关闭文件等。 下表列出了一些 System.IO 命名空间中常用的非抽象类: I/O 类 描述 BinaryReader 从二进制流读取原始数据。 BinaryWriter 以二进制格式写入原始数据。 BufferedStream 字节流的临时存储。 Directory 有助于操作目录结构。 DirectoryInfo 用于对目录执行操作。 DriveInfo 提供驱动器的信息。 File 有助于处理文件。 FileInfo 用于对文件执行操作。 FileStream 用于文件中任何位置的读写。 MemoryStream 用于随机...
