C#基础知识复习2:值和引用-接口-类型转换-异常-函数返回值-对象相等-重载-字符串-垃圾回收-集合

转载 2015年02月15日 07:44:37

1、值类型引用类型

(1)值类型均隐式派生自System.ValueType

数值类型、bool、结构、枚举

查看IL,隐式继承自ValueType

(2)引用类型派生自System.Object

字符串、数组、类、接口等

查看IL隐式继承自Object

引用类型变量的赋值只复制对对象的引用。

值类型变量赋值会拷贝一个副本。

值类型、引用类型作为参数传递

值传递,刚才讨论的参数传递方式都是值传递。

引用传递,ref,传递的是变量的地址。

2、 接口

(1)什么是接口?

接口就是一种规范,协议(*),约定好遵守某种规范就可以写通用的代码。

定义了一组具有各种功能的方法。(只是一种能力,没有具体实现,像抽象方法一样,“光说不做”)

(2)接口存在的意义:多态。多态的意义:程序可扩展性。最终→节省成本,提高效率。

接口解决了类的多继承的问题

接口解决了类继承以后体积庞大的问题。

接口之间可以实现多继承

(3)案例(继承了一个类,同时实现了其他接口)

鸟-麻雀sparrow[‘spærəu],鸵鸟ostrich[‘ɔstritʃ],企鹅penguin[‘pengwin] ,鹦鹉parrot[‘pærət]

鸟能飞,鸵鸟,企鹅不能。。。你怎么办

(4)子类继承抽象类,实现接口

接口中的成员必须不能有实现,接口不能实例化。

接口中的成员不能有访问修饰符,隐式公开public

接口中可以有属性、方法、索引器等(其实都是方法),但不能有字段

接口中的所有成员必须被子类中全部实现,除非子类是抽象类,把接口中的成员标记为抽象的。

(5)显示实现接口(*)

为什么要显示实现接口?

方法重名后的解决办法。

显示实现接口后,只能通过接口来调用。不能通过类对象本身来调用为什么要有“显示实现接口”?

(6)接口的特点总结

a.接口是一种规范。为了多态。

b.接口不能被实例化。

c.接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符为public,不能修改。(默认为public)

d.接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)。

e.接口中只能有方法、属性、索引器、事件,不能有“字段”。

f.接口与接口之间可以继承,并且可以多继承。

g.实现接口的子类必须实现该接口的全部成员。

h.一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。class MyClass:A,IA{},因为类是单继承的。

i.当一个抽象类实现接口的时候,如果不想把接口中的成员实现,可以把该成员实现为abstract。(抽象类也能实现接口,用abstrac标记)

j.“显示实现接口”,只能通过接口变量来调用(因为显示实现接口后成员为private)。

(7)使用接口的建议

a.面向抽象编程,使用抽象(父类、抽象类、接口)不使用具体。

b.“向上转型”

c.在编程时:

接口→抽象类→父类→具体类(在定义方法参数、返回值、声明变量的时候能用抽象就不要用具体。)

能使用接口就不用抽象类,能使用抽象类就不用类,能用父类就不用子类。

避免定义“体积庞大的接口”、“多功能接口”,会造成“接口污染”。只把相关联的一组成员定义到一个接口中(尽量在接口中少定义成员)。单一职责原则应用在了接口上“接口隔离原则”。

定义多个职责单一的接口(小接口)(组合使用)。(印刷术与活字印刷术)

3、类型转换CAST

(1)隐式类型转换

doublenum=10;//sizeof(double)/sizeof(int)

(2)显示类型转换

int n=(int)num;

(3)把学生转换为人是隐式转换,把人转换为学生则是显式转换(强制转换)

Student s = newStudent(); Person p =s;//隐式类型转换

Student stu =(Student)p;//显示类型转换 、obj as 类型。

只有在内存存储上存在交集的类型之间才能进行隐式转换。

不能用Cast转换string/int,只能用Convert。Convert.ToInt32/Convert.ToString

(4)将任意类型转换成字符串:

ToString()

(5)将字符串转换成“数值类型”(int、float、double):

int.Parse(stringstr);、int.TryParse(string str,out int n);//很常用,推荐。

double.Parse(stringstr);、double.TryParse(string str,out double d);

……

Parse()转换失败报异常,TryParse()转换失败不报异常。

(6)再说as与直接类型转换:(*)

if(p isStudent){ Student stu=(Student)p; }

CLR会进行两次类型检查if(检查一次){ //再检查一次 }

通过GetType(),GetType()不允许重写。

Student stu=pas Student;//推荐,效率高于第一种,如果转换失败返回null,而不会报异常。

(7)类型转换Convert

Convert考虑数据意义的转换。Convert是一个加工、改造的过程。

若要进行其它类型的转换可以使用Convert.ToInt32、Convert.ToString等。Convert可以把object类型转换为其它类型

string str= null;
int num= 0;
num = Convert.ToInt32(str);
Console.Write(num +“\r\n”);
num= Int32.Parse(str);
Console.Write(num +“\r\n”);
Int32.TryParse(str, out num);
Console.Write(num +”\r\n”);

当遇到类型转换的时候不知道该怎么转,可以去Convert中找找。

4、异常处理

(1)什么是异常?

程序运行时发生的错误。(错误的出现并不总是程序员人的原因,有时应用程序会因为最终用户或运行代码的环境改变而发生错误。比如:1.连接数据库时数据库服务器停电了;2.操作文件时文件没了、权限不足等;3.计算器用户输入的被除数是0;4.使用对象时对象为null;等等。)

.net为我们把“发现错误(try)”的代码与“处理错误(catch)”的代码分离开来。

(2)异常处理的一般代码模式:

try{ …可能发生异常的代码…}catch{ …对异常的处理… }finally{ …无论是否发生异常、是否捕获异常都会执行的代码… }

try块:可能出问题的代码。当遇到异常时,后续代码不执行。

catch块:对异常的处理。记录日志(log4net),继续向上抛出等操作。(只有发生了异常,才会执行。)

finally块:代码清理、资源释放等。无论是否发生异常都会执行。

(3)异常处理代码的其他几种形式:

try → 多个catch → 一个finally

try→(1个或多个catch),多个catch的顺序问题。可以没有finally。

try→finally(只能有一个),没有catch也可以。

(4)注意点:

发生异常后,try块中,异常代码后的代码不会执行。

finally块中的代码,无论是否发生异常都会执行。

finally中不能写return语句。

try中有return语句,finally也会执行

即便没有catch(或者没有找到合适的catch块),finally中的代码也会执行,但finally之后的代码则不会。(见备注1.)

(5)Exception ex异常也是对象,封装了异常发生时的一些信息。

(6)Exception类主要属性:Message、StackTrace、InnerException(*)

(7)扔出自己的异常,扔:throw,抓住:catch

(8)建议:通过逻辑判断(if-else)减少异常发生的可能性!尽量避免使用“异常处理”。

(9)在多级方法嵌套调用的时候,如果发生了异常,则会终止所有相关方法的调用,并且释放相关的资源。

5、函数返回值(函数参数前的修饰符)

(1)params可变参数 无论有几个参数,必须出现在参数列表的最后。可以为可变参数直接传递一个对应类型的数组。

(2)ref仅仅是一个地址,引用传递,可以把值传递强制改为引用传递

(3)out让函数可以输出多个值

1.在方法中必须为out参数赋值

2.out参数的变量在传递之前不需要赋值,即使赋值了也不能在方法中使用。(赋值没意义)

(4)ref

参数在传递之前必须赋值

在方法中可以不为ref参数赋值,可以直接使用。

(5)ref应用场景内部对外部的值进行改变,out则是内部为外部变量赋值,out一般用在函数有多个返回值的场所。

6、方法重载

(1)方法名称相同

(2)方法签名不同

方法名

参数类型、个数、(顺序)

参数的修饰符(ref、out、params)

不包含方法返回值。

7、Equals、==、ReferenceEquals方法

(1)为什么字符串的Equals和别的不一样?

string的Equals方法判断的是字符串的内容是否相同(重写了Object中的Equals方法。而object中的Equals方法是判断对象的地址是否相同

(2)查看String类的==运算符,内部调用的也是Equals

(3)判断两个对象是否相同要用:object. object.ReferenceEquals();

8、常用类库String

(1)字符串的一些特性:

a.不可变性(ToUpper演示)

b.字符串暂存池(拘留池)(针对字符串常量)

内部维护一个哈希表key为字符串,value是地址。每次为一个新变量赋值都会找key中是否有,如果有则直接把value中的地址赋值给新变量

演示”abc”与控制台输入的”abc”与”a”+”b”+”c”与三个变量abc相加是否为同一个对象,以此说明只针对常量。

c.字符串留用(Intern,针对变量常量,见备注1)。

对于动态字符串本身在哈希表中没有,通过这种Intern可以添加到该哈希表中,目的为了提高性能。

String.Intern(xx),Intern方法使用暂存池来搜索与str 值相等的字符串。如果存在这样的字符串,则返回暂存池中它的引用。如果不存在,则向暂存池添加对str的引用,然后返回该引用。

String.IsInterned(xx),此方法在暂存池中查找str。如果已经将str放入暂存池中,则返回对此实例的引用;否则返回nullNothingnullptrnull引用

(2)String字符串,字符串可以看成字符数组,不可变特性(通过for循环,修改string中的元素,失败!)。

a.属性

Length //获得字符串中字符的个数。”aA我你他”→5

b.方法

IsNullOrEmpty() 静态方法,判断为null或者为””(静态方法)

ToCharArray() 将string转换为char[], new string(char[])

ToLower() 小写,必须接收返回值。(因为:字符串的不可变);

ToUpper() 大写。

Equals() 比较两个字符串是否相同。 忽略大小写的比较,StringComparation.

IndexOf() 如果没有找到对应的数据,返回-1.//面试题:统计一个字符串中,”天安门”出现的次数。

LastIndexOf() 如果没有找到对应的数据,返回-1

Substring() //2个重载,截取字符串。

Split() //分割字符串。

Join() 静态方法

Format () 静态方法

Replace()

9、常用类库StringBuilder

(1)StringBuilder高效的字符串操作

当大量进行字符串操作的时候,比如,很多次的字符串的拼接操作。

String 对象是不可变的。每次使用System.String类中的一个方法时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的String对象相关的系统开销可能会非常大。如果要修改字符串而不创建新的对象,则可以使用System.Text. StringBuilder类。例如,当在一个循环中将许多字符串连接在一起时,使用StringBuilder类可以提升性能。

(2)StringBuilder != String//将StringBuilder转换为String.用ToString();

(3)StringBuilder仅仅是拼接字符串的工具,大多数情况下还需要把StringBuilder转换为String.

StringBuilder sb= new StringBuilder();

sb.Append();//追加字符串

sb.ToString();//把StringBuilder转换为字符串。

sb.Insert();

sb.Replace();

10、垃圾回收(*)

(1)垃圾回收的目的:提高内存利用率。

(2)垃圾回收器,只回收托管堆中的内存资源,不回收其他资源(数据库连接、文件句柄、网络端口等)。

(3)什么样的对象才会被回收?

没有变量引用的对象。没有变量引用的对象,表示可以被回收了(null),断了线的风筝,再也回不来了。

大学食堂(自己收盘子)、大排档(不需要程序员自己收盘子)

(4)什么时间回收?

不确定,当程序需要新内存的时候开始执行回收。

GC.Collect();//手动调用垃圾回收器。不建议使用,垃圾回收时会暂停一下(非常短暂)让程序自动去GC。

(5)垃圾回收器中“代”的概念:

共3代:第0代、第1代、第2代。

各代的回收频率:第0代最高,其次第1代,再次第2代。也就是说越老的对象生存几率越大。

(6).net中垃圾回收机制:mark-and-compact(标记和压缩),一开始假设所有对象都是垃圾。

(7)除了内存资源外的其他资源怎么办?~或者Dispose()

11、.net中的集合

(1)集合命名空间:

usingSystem.Collections;(非泛型集合)

usingSystem.Collections.Generic;(泛型集合)

(2)常用集合

“类似数组”集合:ArrayList、List

“键值对”集合(“哈希表”集合):Hashtable、Dictionary

黑马程序员_学习日记37_601基础加强(enums_truct_类型转换_值类型与引用类型_异常处理_函数返回值)

1、索引器(我理解索引器是给数组提供了成为属性的方法) public class Chinese {        privatestring[] names = new string[]{“乔...

在函数返回值需要使用到强制类型转换时,最好使用指针,光使用引用不保险

这两天发现Android中java上层传递下来的ISurface,我在底层居然画不出图像,但是如果我在底层自己创建ISurface却是可以的...这让我和我同事纠结无比,四处找原因... 由于这个现象...
  • niino
  • niino
  • 2011年03月29日 16:39
  • 2297

友元函数实现左移右移操作符重载(函数返回值当左值需返回引用)(进阶2)

cout 的 #include using namespace std; class Complex{//复数类 private: int a; int b; frie...
  • x_y_q_
  • x_y_q_
  • 2016年08月16日 10:48
  • 449

C/C++语法知识精华整理(2)-栈与堆、内存四大区域、 全局变量、线程技术、位字段、函数返回值副本机制等

1.栈与堆的区别 栈的内存区域只有默认1M 项目设置--连接器,系统,设置默认栈的大小 2.内存四大区域 常量字符串在代码区 char *p = "tas...

将“引用”作为函数返回值类型的格式、好处和需要遵守的规则

格式:类型标识符 &函数名(形参列表能类型说明){ //函数全} 好处:在内存中不门生被返回值的整本 注意:1)不能返回局部变量的引用。因为局部变量在函数运行结束后被销毁,因此被返回的引用也就马为...
  • nocml
  • nocml
  • 2012年02月01日 14:16
  • 1900

函数返回值为引用类型

函数返回值为引用类型 ? #include #include #include using namespace std...

运算符重载--函数返回值

举例 #include  using namespace std; class Test { public:   Test(int a = 0) {cout   Te...
  • Sayesan
  • Sayesan
  • 2015年12月14日 10:52
  • 964

运算符重载--函数返回值

举例 #include  using namespace std; class Test { public:   Test(int a = 0) {cout   Test...

【C++基础07】引用函数返回值(引用当左值)

C++引用使用时的难点: 当函数返回值为引用时 若返回栈变量 不能成为其它引用的初始值 不能作为左值使用 若返回静态变量或全局变量 可以成为其他引用的初始值 即可作为右值使用,也可作为左值使...

C#值类型与引用类型、 out 、 ref、 params 参数、函数重载、数组为函数参数或返回值

1、 在C#中方法是将一堆代码进行重用的一种机制; 若调用类中的方法时,若类与Main()函数在一个类中是,类名可以省略,若不在一个类中,类名不可以省略; 2 、 返回值为数组的函数 public ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#基础知识复习2:值和引用-接口-类型转换-异常-函数返回值-对象相等-重载-字符串-垃圾回收-集合
举报原因:
原因补充:

(最多只允许输入30个字)