C#基础知识(需要特别注意的知识点)(共16页).docx

上传人:飞****2 文档编号:14078834 上传时间:2022-05-02 格式:DOCX 页数:16 大小:41.26KB
返回 下载 相关 举报
C#基础知识(需要特别注意的知识点)(共16页).docx_第1页
第1页 / 共16页
C#基础知识(需要特别注意的知识点)(共16页).docx_第2页
第2页 / 共16页
点击查看更多>>
资源描述

《C#基础知识(需要特别注意的知识点)(共16页).docx》由会员分享,可在线阅读,更多相关《C#基础知识(需要特别注意的知识点)(共16页).docx(16页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、精选优质文档-倾情为你奉上C#4.0本质论学习笔记一、 值类型和引用类型的区别值类型引用类型1. 直接包含值,变量引用的位置就是值在内存中实际存储的位置。存储是对一个内存位置的引用(内存地址),要去那个位置才能找到真正的数据2. 数据存储在栈的内存区域中数据存储在堆的内存区域3. 在编译时确定内存量在运行时,从变量中读取内存地址,然后到指定内存地址中读取数据。4. 复制数据的一个副本只复制数据的地址5. 将new用于值类型,会使用默认值初始化内存new,调用构造函数生成一个对象(实例)二、 装箱与拆箱1. 装箱:将一个值类型转换成一个引用类型1) 首先在堆中分配好内存;2) 一次内存复制:栈上

2、的值类型数据复制到堆上分配好的位置;3) 对象或接口引用得到更新,指向堆上的位置。2. 拆箱:将一个引用类型转换为值类型3. 装箱频繁发生,会大幅影响性能;4. 不允许在lock()语句中使用值类型。三、 String 与StringBuilder1. String 对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值2. StringBuilder此类表示值为可变字符序列的类似字符串的对象3. 对象串联操作总是用现有字符串和新数据创建新的对象。StringBuilder 对象维护一个缓冲区,以便容纳新数据的串联。如果有足够的空间,新数据将被追加到缓冲区的末尾;否则,将分配一个

3、新的、更大的缓冲区,原始缓冲区中的数据被复制到新的缓冲区,然后将新数据追加到新的缓冲区。4. 或 StringBuilder 对象的串联操作的性能取决于内存分配的发生频率。 串联操作每次都分配内存,而 StringBuilder 串联操作仅当 StringBuilder 对象缓冲区太小而无法容纳新数据时才分配内存。因此,如果串联固定数量的 对象,则 类更适合串联操作。这种情况下,编译器甚至会将各个串联操作组合到一个操作中。如果串联任意数量的字符串,则 StringBuilder 对象更适合串联操作;例如,某个循环对用户输入的任意数量的字符串进行串联。四、 ? 和 ?的使用1. 可空修饰符 ?:

4、为了声明可以存null的值类型变量。int ?x=null;2. 使用 ? 运算符分配默认值:expression1?expression2.检查第一个表达式是否为null,如果为null,则返回第二个表达式。3. 当前值为空的可以为 null 的类型被赋值给非空类型时将应用该默认值,如 int? x = null; int y = x ? -1;。三、const和readonly1. const:1) 既然用于修饰字段,又可以修饰局部变量;2) 是在编译时确定的值,不可以在运行时改变;3) 自动成为静态字段,不能显式声明为static2. readonly:1) 只能用于字段(不能用于局部变

5、量),2) 指出字段值只能从构造函数中更改,或者直接在声明时指定。可以在运行时赋值;3) readony字段既可以是实例字段,也可以是静态字段.四、静态成员和实例成员1. 静态字段:主要存储的是对于类的数据,能由多个实例共享,需要使用static关键字2. 实例字段:存储的是与对象关联的数据,只能从类的一个实例(对象)中访问实例字段。3. 静态方法:不能直接访问一个类中的实例字段,必须获取类的一个实例,才能调用任一实例成员(方法或字段)。4. 实例方法:将需要访问实例数据的方法声明为实例方法。5. 静态构造函数:用来对类(而不是类实例)进行初始化。 运行时会在“访问类的一个静态方法或者字段时”

6、自动调用静态构造函数。6. 静态类:不包含任何实例字段(或方法),声明时用static 关键字。不能被实例化,不能被继承。五、 继承:对一个现有的类型进行扩展,以包含附加的成员或实现对基类成员的定制。1 protected 访问修饰符: 在基类中定义只有派生类才能访问的成员。规则:要从一个派生类中访问一个受保护的成员,必须在编译时确定受保护的成员是派生类(或者它的某个子类)的一个实例。 2 C#是一种单一继承的语言,一个类不能直接从两个类派生。3 可以使用聚合解决多重继承的问题4 使用sealed修饰符,实现密封类(不能被继承)5 C#支持重写实例方法和属性,但不支持重写字段或者任何静态成员。

7、1) 在基类中使用virtual修饰符标记每一个需要重写的成员,2) 在派生类中,用override进行修饰。C#要求重写方法显式地使用override关键字。3) 重写一个成员时,会造成“运行时”调用派生得最远的实现。4) new 修饰符:在基类面前隐藏了派生类的重新声明的成员。6 抽象类:1) 仅供派生的类,不能被实例化。 2) 包含抽象成员:不具有实现的一个方法或属性,强制所有派生类提供实现。7 多态性:同一个签名可以有多个实现。1) 抽象成员是实现多态性的一个手段:基类指定方法的签名,派生类提供具体的实现;2) 可以利用多态性:调用基类的方法,当方法具体由派生类实现。8 is 和as运

8、算符1) is运算符验证基础类型2) 使用as运算符进行转换:将对象转换为一个特定的数据类型,若源类型不是固有的目标类型,as运算符会将null值赋给目标。六、 接口1. 对接口的理解:1)接口定义了一系列成员,不包含任何实现,由继承该接口的类实现;2)接口实现关系是一个“能做”关系:类“能做”接口要求的事情;3)接口定义了一个“契约”:实现接口的类会使用与被实现的接口相同的签名来定义方法。4) 接口的宗旨是:定义由多个类共同遵守的一个契约,所有成员都自动定义为public。5) C#不允许为接口成员使用访问修饰符。6) 通过接口可以实现多态性;7) 不能被实例化,不能使用new关键字来创建一

9、个接口。2. 接口实现:1) 一个类只能从一个基类派生,但可以实现多个接口;2) 显式实现: 为了声明一个显式接口成员实现,需要在成员名之前附加接口名前缀。String IListable.ColumnValues.通过接口本身来调用它将对象转型为接口;Values=(IListable)contact1).Columnvalues3) 隐式实现:类成员的签名与接口成员的签名相符。 调用时不需要转型,可以直接调用。4) 成员若是核心的类功能,则隐式实现;5) 假如一个成员的用途在实现类中不是很明确,就考虑使用一个显式的实现;6) 已经有一个同名的类成员,则可以使用显式实现。3. 接口继承:1)

10、 一个接口可以从另一个接口派生,派生的接口将继承“基接口”的所有成员;2) 在用于显式接口成员实现的一个完全限定的接口成员名称中,必须引用最初声明它的那个接口的名称;3) 继承:接口代表一份契约,而一份契约可指定另一份契约也必须遵守的条款。4) 通过接口可以实现多重继承。 4. 接口与类的比较抽象类接口仅供派生的类,不能被实例化不能实例化定义了基类必须实现的抽象成员签名接口的所有成员要在基类中实现可以包含存储在字段中的数据不能存储任何数据。只能在派生类中指定字段。解决这个问题的办法,是在接口中定义属性,但不能包括实现。扩展性比接口好,不会破坏任何版本兼容性。在抽象类中,你可以添加附加的非抽象成

11、员,它们可以由所有派生类继承用更多的成员来扩展接口,会破坏版本兼容性。(只能再创建一个接口,该接口可以从原始接口派生)七、 重写Equals()1. “对象同一性”和“相等的对象值”1) 对象同一性:两个引用,引用的是同一个实例;2) 相等的对象值:两个引用,引用不同的实例,但两个对象实例值是相等的。3) 只有引用类型才可能引用相等,值类型不可能引用相等(ReferenceEquals()对值类型进行了装箱,由于每一个实参都被装到栈上的不同位置)。2. 实现Equals():1) 检查是否为null;2) 如果是引用类型,就检查引用是否相等;(ReferenceEquals()方法来判断引用是

12、否相等)3) 检查数据类型是否相等;4) 调用一个指定了具体类型的辅助方法,它能将操作数视为要比较的类型,而不是一个对象;5) 可能要检查散列码是否相等。(相等的两个对象,不可能散列码不同)6) 如果基类重写了Equals(),就检查base.Equals();7) 比较每一个标识字段,判断是否相等;8) 重写GetHashCode()。9) 重写=和!=运算符。八、 垃圾回收与资源清理1. 垃圾回收 内存1) “运行时”的一个核心功能:回收不再被引用的对象所占用的内存。2) 垃圾回收器只负责回收内存,不处理其他资源,比如数据库连接、句柄(文件、窗口等)、网络端口以及硬件设备(比如串口)等;3

13、) 垃圾回收器处理的是引用对象,而且只回收堆上的内存;2. 终结器 释放资源1) 终结器:允许程序员编写代码来清理一个类的资源;2) 由垃圾回收器负责为一个对象实例调用终结器;3) 终结器会在上一次使用对象之后,并在应用程序关闭之前的某个时间运行。4) 终结器不允许传递任何参数,不能被重载,不能被显式调用,不允许使用访问修饰符;5) 终结器负责释放像数据库连接和文件句柄这样的资源,不负责回收内存(回收内存是由垃圾回收器完成)6) 避免在终结器中出现异常,比如采用空值检查。3. 使用using语句进行确定性终结:1) IDisposable接口用一个名为Dispose()的方法释放当前消耗的资源

14、;2) using语句在对象离开作用域时自动调用Dispose()方法释放资源。4. 垃圾回收和终结1) f-reachable队列(终结队列):是准备好进行垃圾回收,同时实现终结的所有对象的一个列表;2) 假如一个对象有终结器,那么“运行时”只有在对象的终结方法被调用之后,才能对这个对象执行垃圾回收;3) f-reachable队列是一个“引用”列表,一个对象只有在它的终结方法得到调用,而且对象引用从f-reachable队列中删除之后,才会成为“垃圾”。九、 泛型1. 泛型类型概述:1) 利用泛型,可以在声明变量时创建用来处理特定类型的特殊数据结构;2) 参数化类型,使特定泛型类型的每个变

15、量都有相同的内部算法;3) 声明泛型类:public class Stackprivate T _Items;public void Push(T data).Public T Pop()2. 泛型的优点:1) 提供了一个强类型的编程模型:确保在参数化的类中,只有成员明确希望的数据类型才可以使用;2) 为泛型类成员使用值类型,不再造成到object的强制转换,它们不再需要装箱操作;3) 性能得到了提高:不再需要从object的强制转换,从而避免了类型检查;不再需要为值类型执行装箱操作4) 由于避免了装箱,因此减少了堆上的内存的消耗;3. 泛型接口:1) 声明一个泛型接口:Interface I

16、PairT First get;set; T Second get;set2) 使用泛型接口,就可以避免执行转型,因为参数化的接口能实现更强的编译时绑定;3) 在一个类中多次实现相同的接口:可以使用不同的类型参数来多次实现同一个接口。4. 多个类型参数:1) 泛型类型可以使用任意数量的类型参数;2) 声明:Interface IPair TFirst First get;set; TSecond Second get;setPublic struct Pair:IPairPublic Pair(TFirst first,TSecond second)_First=first; _Second=

17、second;.5. 约束1) 泛型允许为类型参数定义约束。这些约束强迫类型遵守各种规则;2) 约束声明了泛型要求的类型参数的特征。3) 为了声明一个约束,需要使用where关键字,后跟一对“参数:要求”;其中,“参数”必须是泛型类型中定义的一个参数,而“要求”用于限制类型从中派生的类或接口,或者限制必须存在一个默认构造器,或者限制使用一个引用/值类型约束。4) 接口约束:为了规定某个数据类型是必须实现某个接口,需要声明一个接口约束。不需要执行转型,就可以调用一个显式的接口成员实现。声明一个接口约束:public class BinaryTreewhere T:System.IComparab

18、lePublic PairBinaryTree SubItems getreturn _SubItems;setIComparable first;First=value.First.Item;.5) 基类约束:将构建的类型限制为一个特定的类派生。6) struct约束:将类型参数限制为一个值类型;7) class约束:将类型参数限制为一个引用类型。8) 多个约束:对于任何给定的类型参数,都可以指定任意数量的接口作为约束,但基类约束只能指定一个,因为一个类可以实现任意数量的接口,但肯定只能从一个类继承。public class EntityDictionary: Dictionarywhere

19、 TKey: IComparable,IFormattable /多个约束接口where TValue: EntityBase /一个基类约束 9) 构造器约束:可以在指定了其他所有约束之后添加new() ,指定类型参数必须有一个默认构造器。10) 继承约束:约束可以由一个派生类继承,但必须在派生类中显式地指定这些约束。6. 泛型方法1) 即使包容类不是泛型类,或者方法包含的类型参数不在泛型类的类型参数列表中,也依然使用泛型的方法;2) 为了定义泛型方法,需要紧接在方法名之后添加类型参数语法; 7. 协变性和逆变性1) 协变性:将一个较具体的类型赋给较泛化的类型。2) 逆变性:将较泛化的类型赋

20、给较具体的类型;3) 在C#4.0中使用out类型参数修饰符允许协变性;4) 在C#4.0中使用int类型参数修饰符允许逆变性;8. 泛型的内部机制:1) 基于值类型的泛型的实例化:“运行时”会为每个新的参数值类型创建新的具体化泛型类型。2) 基于引用类型的泛型的实例化:使用一个引用类型作为类型参数来首次构造一个泛型类型时,“运行时”会创建一个具体化的泛型类型,并在CIL代码中用object引用替换类型参数。以后,“运行时”都会重用以前生成好的泛型类型的版本即使新的引用类型与第一次使用的引用类型不同。十、 委托、Lambda表达式1. 委托:将方法作为对象封装起来,允许在“运行时”间接地绑定一

21、个方法调用;2. 所有委托类型都间接从System.Delegate派生,但System.Delegate不能显式的成为一个基类;3. 声明委托数据类型:Public delegate bool ComparisonHandler(int first,int second);4. 实例化委托:需要和委托类型自身的签名对应的一个方法(相同的参数及参数类型、相同的返回值);class DelegateSamplepublic delegate bool ComparisonHanlder(int first, int second);public static void BubbleSort(in

22、t items, ComparisonHanlder comparisonMethod)int i, j, temp; for (i = items.Length - 1; i = 0; i-) for (j = 1; j second; static void Main(string args) int i; int items = new int5; for (i = 0; i items.Length; i+) Console.Write(Enter an integer:); itemsi = int.Parse(Console.ReadLine(); BubbleSort(items

23、, GreaterThan); for (i = 0; i second;);6. 系统定义的委托:Func 1) 在C#3.0中,存在一系列名为“Action”和“Func”的泛型委托;2) System.Action代表无返回类型的委托;3) System.Func代表有返回类型的委托;4) Func的最后一个类型参数总是委托的返回类型,在它之前的类型参数则依次对应于委托参数的类型;5) 可以用一个Func泛型委托来代替一个显式定义的委托。ComparisonHandler可以用Func来代替 7. Lambda表达式1) Lambda表达式分为:语句Lambda和表达式Lambda;2)

24、 Lambda运算符 =,可以理解成“用于”;3) 使用语句Lambda来传递委托:BubbleSort(items, (int first,int second) =return firstsecond;);4) C#要求用一对圆括号来封闭Lambda表达式的参数列表,不管是否指定了这些参数的数据类型;5) 当编译器能判断出数据类型,而且只有一个输入参数的时候,语句Lambda可以带圆括号;IEnumerable processes=Process.GetProcesses().Where(process=return process.WorkingSet64230;);6) 语句Lambd

25、a含有一个语句块,所以可以包含零个或者更多的语句,而表达式Lambda只有一个表达式,没有语句块;此时将Lambda运算符理解成“满足条件”;BubbleSort(items,(first,second)=firstperson.Name.ToUpper()=”INIGO MONTOYA”);假定persons是一个Person数组,编译器将Lambda表达式编译成一个Func委托类型,然后将委托实例传给Where()方法。9) 表达式树:如果一种Lambda表达式代表的是与表达式有关的数据,而不是编译好的代码,这种Lambda表达式就是“表达式树”;10) 表达式树转换成的数据是一个对象图,

26、它由System.Linq.Expressions.Expression表示。11) Lambda表达式和表达式树的比较: 表达式的语法都会在编译时进行完整的语义分析验证;但是,Lambda表达式在CIL中被编译成一个委托,而表达式树被编译成System.Linq.Expressions.Expression类型的一个数据结构。十一、 事件1. 多播委托:一个委托变量可以引用一系列委托,在这一系列委托中,每个委托都顺序指向一个后续的委托,从而形成了一个委托链。2. 使用多播委托来编码Observer模式(又叫publish-subscribe模式):1) 定义订阅者方法:参数和返回类型必须和来

27、自发布者类的委托匹配2) 定义发布者:只需一个委托字段,就可以存储所有的订阅者3) 连接发布者和订阅者;4) 调用委托:当发布者中的属性每次发生变化时,向订阅者通知变化; /call subscribers OnTemperatureChange(value);/将温度的变化发给多个订阅值cooler和heater对象5) 检查空值:调用一个委托之前,要检查它的值是不是空值;6) 将“-=”运算符应用于委托会返回一个新实例;7) 委托运算符:+=,获取第一个委托,并将第二个委托添加到委托链中,使一个委托指向下一个委托。第一个委托的方法调用之后,它会调用第二个委托。8) +,-,-=,+=运算符

28、,在内部都是使用静态方法System.Delegate.Combine()和System.Delegate.Remove()来实现的。9) 顺序调用10) 例子: /订阅者1 class Cooler private float _Temperature; public float Temperature get return _Temperature; set _Temperature = value; public Cooler(float temperature) Temperature = temperature; public void OnTemperatureChanged(fl

29、oat newTemperature) if (newTemperature Temperature) System.Console.WriteLine(Cooler:On); else System.Console.WriteLine(Cooler:Off); /订阅者2 class Heater private float _Temperature; public float Temperature get return _Temperature; set _Temperature = value; public Heater(float temperature) Temperature

30、= temperature; public void OnTemperatureChanged(float newTemperature) if (newTemperature Temperature) System.Console.WriteLine(Cooler:On); else System.Console.WriteLine(Cooler:Off); /定义发布者 class Thermostat public delegate void TemperatureChangeHandler(float newTemperature); /define the event publish

31、er public TemperatureChangeHandler OnTemperatureChange get return _OnTemperatureChange; set _OnTemperatureChange = value; private TemperatureChangeHandler _OnTemperatureChange; public float CurrentTemperature get return _CurrentTemperature; set if (value != CurrentTemperature) _CurrentTemperature =

32、value;/检查空值 TemperatureChangeHandler localOnChange = OnTemperatureChange; if (localOnChange != null) /call subscribers OnTemperatureChange(value);/将温度的变化发给多个订阅值cooler和heater对象 private float _CurrentTemperature;/连接发布者和订阅者class Program static void Main(string args) Thermostat thermostat = new Thermost

33、at(); Heater heater = new Heater(60); Cooler cooler = new Cooler(80); string temperature; thermostat.OnTemperatureChange += heater.OnTemperatureChanged; thermostat.OnTemperatureChange += cooler.OnTemperatureChanged; Console.Write(Enter temperature:); temperature = Console.ReadLine(); thermostat.Curr

34、entTemperature = int.Parse(temperature); Console.ReadLine(); 3. 事件1) 事件的作用:封装订阅(使用event关键字,避免不小心取消了其他订阅者),封装发布(只有包容类才能触发一个事件通知);2) 事件的编码规范:第一个参数sender是object类型的,它包含对调用委托的那个对象的一个引用,第二个参数是System.EventArgs类型的(或者是从System.EventArgs派生,但包含了事件附加数据的其他类型)。3) 泛型和委托:使用泛型,就可以在多个位置使用相同的委托数据类型,并在支持多个不同的参数类型的同时保持强类

35、型;4) 声明泛型委托类型:public delegate void EventHandler(object sender,T e) where T:EventArgs;使用EventHanlder,任何类如果需要一个特定的sender-EventArgs模式,都不必声明它自己的委托定义。相反,它们可以共享同一个委托。5)十二、 集合、Linq查询1. 匿名类型:1) 完全由C#编译器来实现的,而不会在“运行时”内有显式实现;2) 当编译器遇到匿名类型的语法时,会自动生成一个CIL类,其属性和在匿名类型声明中命名的值和数据类型是对应的;3) 使用匿名类型的隐式局部变量:var patent1=

36、newTitle=”Hello”, Value=”World” ;4) 是强类型的。5) 匿名类型是不可变的:一经实例化,再更改它的某个属性,就会造成编译错误;6) 类型兼容:在同一程序集中,两个匿名类型类型兼容的必要条件为属性名、数据类型和属性顺序都完全匹配。2. 隐式类型的局部变量:1) 遇到一个隐式类型的变量时,编译器会首先分析右侧的表达式,确定它的类型,根据所赋的数据类型来确定该变量的数据类型;2) 遇到显式类型的局部变量时(而且声明的同时已赋值),比如 string s=”Hello”;编译器首先会根据左侧明确声明的类型来确定s的类型,然后分析右侧的表达式,验证右侧的表达式是否适合赋

37、给那个类型的变量;3. 集合初始化器:1) 使用集合初始化器,程序员可以采取和数组声明相似的方式,在一个集合的实例化期间用一套初始的成员来构造这个集合。4. foreach和IEnumerable1) System.Collections.Generic.IEnumerator和非泛型System.Collections.IEnumerator接口:允许用迭代器模式来遍历元素集合;2) IEnumerator从IEnumerator派生,IEnumerator接口包含3个成员:bool MoveNext(),从集合中的一个元素移动到下一个元素;只读属性Current,它返回当前元素;Reset

38、()方法抛出一个NotImplementedException;3) 集合不直接支持IEnumerator和IEnumerator接口;4) IEnumerable接口,唯一的方法就是GetEnumerator():返回支持IEnumerator的一个对象。5. 推迟执行1) Lambda表达式是可以传递到别的地方的委托是一个对方法的引用;声明时,不执行,在调用时才执行。2) 隐式触发Lambda表达式的执行:foreach循环内会触发Lambda表达式的执行;调用Enumberable的Count()函数,会再次为每一项触发Lambda表达式;调用ToArray()或者ToList()、To

39、Dictionary、ToLookup(),会为每一项触发Lambda表达式;3) 使用“ToXXX”方法来转换集合,返回的是标准查询运算符已处理过的一个集合;此时再遍历新的结果集合,则不会再触发Lambda表达式6. 查询表达式Linq1) 输出的是一个IEnumerable或IQueryable集合;2) from 后面紧着的,是集合中的每一项3) 在select子句中,可以对from子句的表达式所收集到的东西进行投射,获得完全不同的一个数据类型;4) 也是支持推迟执行的。5) C#编译器将查询表达式转换成CLR能理解的方法调用6) 实现隐式执行:编译器将查询表达式转换成在目标上调用的方法,它获取委托作为参数,直到以后执行时才拿出来使用。7. 集合1) 集合接口:IList:用于支持通过索引来获取值;继承ICollectionIDictionary:通过键来获取值;继承ICollectionIComparable:实现排序,有一个CompareTo

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁