第一部分 重点基础

基础部分

1、 快捷键

Ctrl+e+d快速对齐代码

Ctrl+S保存

Ctrl+z撤销

Ctrl+k+c注释代码

Ctrl+k+u取消注释代码

#region#endregion 折叠代码

Ctrl+鼠标滚动 放大,缩小界面

双击tab键,自动出现console.writeline();

ctrl+. 或者 shift+alt+F10 导入命名空间(using)(当关键字下面出现提示的时候)

ctrl+r+e : 自动封装属性

2、 数据类型

Int 整型

Double 浮点型,可带小数

Float 浮点型

String 字符串 ,加双引号

Char 单个字符,加单引号

Decimal 金钱,钱数后要加”m”

3、“+”号

有一边有字符类型,起到连接的作用。

两边都是数字,就是相加。

3、 占位符”{}”

用在输出方法中。

例:

String name=”匡“

Int age=30;

Console.Writeline(我叫{0},我今年{1},name,age);

4、 输入、输出

Consoe.writeline(“请输入您的姓名”);//提示输入姓名,把这行字显示到显示屏上

String name=Consle.readline(); //定义一个name字符串变量,把输入的值存入变量

Consoe.writeline(“您的姓名是{0}”,name);

Console.readkey();

5、 转义符\+特殊字符组成有特殊意义的字符\n 换行

\r\nwindows系统的换行

\t TAB键的空格

\” 双引号

\b 表示一个退格符

\\ 表示右斜杠。

6、@

@ 取消\在字符中的转义作用,例 sting str=@”f:\file\rmvb\1.rmvb”;一般在有路径的情况下加@符号,取消右斜杠的转义作用。

@还可以保留原格式输出

7、 转换

(1)隐式转换 (小的转换成大的,可以自动隐式转换,如int转换成double,double就不能隐式转换成int)

Int a=3

Double b=3.14

double c=a*b //隐式把int 的变量a,转换成double类型。

(2)显示转换(大的转成小的,就必须显式转换,必须兼容)

Int a=3

Double b=3.14

Int c=a*(int) b //显式的把double转换成int类型

(3)convert 转换(类型不兼容的情况下用,但也有限制,如不能把字符abc,转换成double或int)

String s=”123”;

Double d=Convert.ToDouble(s);//把string类型的变量转换成double类型,赋值给变量d.

Int c=Convert.ToInt32(s); //把string类型的变量转换成int类型,赋值给变量c.

8、++,--

(1)++

例:

Int a=10;

Int b=10+a++;

上面这一个语句,可以用下面两条语句表达:

{int b=10+a; //此时b=20

a++;//此时a=11, a++即a=a+1

}

例:

Int a=10;

Int b=10+ ++a;

上面这一个语句,可以用下面两条语句表达:

{

a++;//此时a=11, a++即a=a+1

int b=10+a;//此时b=21

}

++在前,即先自身加1,再参加运算。

++在后,即先用原值参加运算,然后自身再加1.

9、 关系表达式和布尔关型

==

>

<

>=

<=

!=

关系运算符连接的表达式,称之为关系表达式。关系表达式的结果只有对和错两种。用布尔类型来反应。

例:

Bool b=38>39; //因为38小于39,所以这是b的值为False.

10、逻辑运算符

一般两边是布尔类型或关系表达式。

&&与

|| 或

! 非

11、复合赋值运算符

+=

-+

*=

/=

%=

11、调试

(1)F11单步调试:从头至尾一行一行的调试。

(2)F10 方法调试

(3) 断点调试,先在想设断点的代码左边点击鼠标,再点击启动,然后再按F11一步一步调试。

可以在调试,窗口中,调出监视窗口来监视变量

语句

1、if else

(1)if

if(判断) //判断为真执行下面的语句。判断为真后,只执行一遍下面的语句,不循环。

{ }

(2)if else

If(判断) //判断为真执行下面的语句,为假则执行ELSE里的语句。

{ }

Else

{ }

注意,else语句匹配离他最近的if语句。

(3)if else-if //如果第一个if判断为真,则执行下面大括号的语句,然后跳出,不进行后面的所有判断。

If(判断) //主要用来处理多条件区间性判断。多条件固定值判断一般用switch

{ }

Else if (判断)

{ }

Else if (判断)

{ }

…….

Else

{ }

2、switch

switch(变量或表达式的值) //先算出变量或表达式的值,然后用算出的值与下面catch语句里的值进行匹配,匹配成功,就执行后面的代码,遇到break语句,跳出switch语句。如果不成功继续与下面的catch里的值进行匹配,直到匹配为止,如果都不匹配,则看是否有default语句,有的话就执行default语句中的代码,然后跳出switch。

catch 值1:要执行的代码

break;

catch 值2:要执行的代码

break;

catch 值3:要执行的代码

break;

……

default:要执行的代码 //都不匹配就执行default里的代码

break;

3、 while

(1)while

while(循环条件) //当判断循环条件成立时,则执行下面的循环体,执行完循环体中的代码后,再进行循环条件判断,如成立,继续执行循环体,如不成立则跳出while。循环条件一般为布尔类型或表达式。

{ 循环体

}

(2)do while

Do

{ 循环体}

While(循环条件) //先执行一遍循环体,再进行循环条件的判断,判断为真继续执行循环体,否则跳出do while循环。

4、 for (已经知道循环次数时用for)

for (表达式1,表达式2,表达式3)

{循环体}

表达式1为声明循环变量,计录循环次数。如,int i=0

表达式2为循环条件,如i<10

表达式3为改变循环条件的代码,使循环条件终有不成立的时候,如i++。

5、 break和continue

(1)break

跳出当前循环体,不再循环。一般不单独出现,和if一起用,当满足某种条件是跳出循环体。

(2)continue

跳出本轮循环,重新检测循环条件,继续下一轮循环。一般也和if一起用。

Break和contunue的区别好比跑步,如果要跑100圈,当跑到10圈遇到break时,直接不跑了,干其他没干完的事去了。而遇到continue时,你只是临时下场,这一圈不跑了,然后再上场接下来跑余下的90圈。

三、异常

1、try catchfinally

try //捕捉异常,包含被异常保护的代码

{}

Catch (可带异常变量,匹配执行某类型的异常) //如果出现异常,将执行的代码

{}

Catch (可带异常变量,匹配执行某类型的异常) //如果出现异常,将执行的代码

{}

……

Finally //不管出不出现异常,都将执行的代码

{ }

2、throw

数据类型详解

(一)数据类型简介

浮点型:

Float

Double

Decimal

整数型:

Int

Uint

Long

Short

……..

非数值型:

Bool 布尔

Char 单个字符

用户自定义类型:

类 class

结构 struct

枚举 enum

委托 delegate

接口 interface

数组 arry

(二)数据类型详解

1、 常量 用在不更改的数据上面。如超市统一的打折率。

Const 变量类型 变量名=值; //常量声明时必须赋值,且赋值后就不能再更改。

Const int number=50; //值就一直为50,不能重新赋值。

Number=40//这就会出错。不能改。

2、 枚举

(1)语法:

[public] enum 枚举名:枚举值类型 (一般枚举值类型是省略的)

{

值1, //默认为值1=0;

值2, //默认为值2=1;

值3, //如果此处值3=10;,则值4=11,以此类推。

........

}

public:访问修饰符。公开的公共的,哪都可以访问。

enum:关键字,声明枚举的关键字

枚举名:要符合Pascal命名规范

枚举是值类型,和Int等类似。

枚举只能存储同一类型的数据。

(2)枚举的转换

Int类型可以和枚举互转。

枚举可以转换成字符串类型,用tostring()方法。

字符串类型转换成枚举类型时用parse()方法。

3、 结构

语法:

[public] struct 结构名

{

成员;//字段,默认是Private类型,要想对外可访问,要加Public。

}

变量在程序运行期间只能存储一个值,而字段可以存储多个值。

4、 数组

数组类型[] 数组名=new 数组类型[数组长度];

二维或三维就是增加[],

如int [][] number=new int[2][3];//二维数组,两列三行的数组,实例化是一定要指定长度,或直接初始化。

***数组的长度一旦固定了,就不能再被改变了

5、 事件

方法(函数)就是将一堆代码进行重用的一种机制。

1、 方法的语法:

函数的语法:

[public] static 返回值类型 方法名([参数列表])

{

方法体;

}

public:访问修饰符,公开的,公共的,哪都可以访问。

static:静态的

返回值类型:如果不需要写返回值,写void

方法名:Pascal 每个单词的首字母都大些。其余字母小写

参数列表:完成这个方法所必须要提供给这个方法的条件。如果没有参数,小括号也不能省略。

方法写好后,如果想要被执行,必须要在Main()函数中调用。

2、 方法的调用与传递

类名.方法名([参数]);

在某些情况下,类名是可以省略的,如果你写的方法跟Main()函数同在一个类中,这个时候,

类名可以省略。

参数传递方法有:

值传递

引用传递

当方法声明有返回值类型时,方法体中一定要用return返回一个同类型的值。

3、 Ref

引用参数,传输的是变量的地址值,所以不管是调用代码中,还是方法体内的更改,值变量值都会发生改变。

reft参数一定要在方法外赋值,方法内可以不用赋值。如在调用代码中先赋值。

可以把值传进方法,也可以把值从方法中传出来。

staticvoid Main(string[] args)

{

double salary = 5000;

JiangJin(ref salary);//虽然没有返回值,但代码中调用jiangjin方法后,salary的值变成了5500.

Console.WriteLine(salary);//此处值为5500。

Console.ReadKey();

}

publicstaticvoid JiangJin(refdouble s)//此时是参数S的地址值,所以此方法中如果改变了参数的值,在调用代码中也会改变。所以此处也没有返回值。

{

s += 500;

}

4、 Out

传输多余的变量值到调用代码中,只能把方法内的数据传出去,不能传进来。

一般用在一个方法中需要返回多个数据类型的值时。如既需要string类型,也需要返回int类型时。

调用的方法中有out关键时,调用代码中也需要加上out关键字

out参数一定要在方法内初始化赋值。

{ Console.WriteLine("请输入用户名");

string userName = Console.ReadLine();

Console.WriteLine("请输入密码");

string userPwd = Console.ReadLine();

string msg1; //此处可以赋初值也可以不赋初值,因为此参数是out实参,out实参在方法体中会赋初值,且会把最终返回值到此处。且实参名不必和形参名一样,但实参一定要声明不可省略。

bool b = IsLogin(userName, userPwd, out msg1);//调用IsLogin函数,传递实参到方法的形参中去。此处调用方法的返回值是bool类型,而多余返回值为msg1是string类型。且此处一定要加上out关键字。

Console.WriteLine("登陆结果{0}",b);

Console.WriteLine("登陆信息{0}",msg1);

Console.ReadKey();

}

///<summary>

///判断登陆是否成功

///</summary>

///<param name="name">用户名</param>

///<param name="pwd">密码</param>

///<param name="msg">多余返回的登陆信息</param>

///<returns>返回登陆结果</returns>

publicstaticbool IsLogin(string name, string pwd, outstring msg)//此方法的返回值为bool类型,同时传递两个参数值和一个多余参数值过来,返回时,会返回一个bool类型的方法返回值,还会多余返回一个string类型的返回值。且多余返回形参前面一定要加Out关键值。

{

if (name == "admin" && pwd == "888888")

{

msg = "登陆成功"; //给out参数赋值。

returntrue;

}

elseif (name == "admin")

{

msg = "密码错误"; /给out参数赋值。

returnfalse;

}

elseif (pwd == "888888")

{

msg = "用户名错误";

returnfalse;

}

else

{

msg = "未知错误";

returnfalse;

}

5、 Pars

6、 方法重载

概念:方法的重载指的就是方法的名称相同给,但是参数不同。

参数不同,分为两种情况

1)、如果参数的个数相同,那么参数的类型就不能相同。

2)、如果参数的类型相同,那么参数的个数就不能相同。

***方法的重载跟返回值没有关系,即如果仅仅返回值不同,构成不了重载。

7、 方法的递归

自已调用自已。

要考虑到入口,再考虑到出口。即一定要考虑到什么时候停止调用自已。不然就死循环了。

你调用多少次递归,就要有多少次返回。如你画圈,调用递归你画了十层圈,你不能通过return就立即跳出十层圈,而是得一层一层的跳,要跳十次才能跳出。

六、类

1、 基本语法

[public] [static]class 类名

{

字段; //在外面叫变量,在类里叫字段。在类里如果不加修饰符,默认为private。

属性; //实质上就是get和set方法,主要是为了保护字段。

方法; //实现方法。

构造函数; //主要是初始化类,如果不定义构造函数,系统会自动生成一个默认的。

析构函数; //释放类的资源和空间。

}

创建类的对象过程,叫类的实例化。

2、 修饰符

Public:公开的。类里的成员可访问、类外的成员可以通过类对象访问、派生类的成员可以直接访问。

Private:私有的,只在当前类内部访问。只有类里的成员可以访问,就算是本类的实例化对象也不能访问。

Protected:保护的,只有当前类内部和派生类(子类)可以访问,孙子辈也可访问。。

Internal:当前程序集中访问。(当前项目中访问),在同一项目中,和public权限是一样的。修饰类时,不加修饰符时,Internal是默认修饰符。

Protected internal:protected+internal的权限。

只有public 和intenal可修饰类类型,如: public class test(){};

子类的访问权限不能高于基类,会暴露父类的成员。

3、属性(在字段下按快捷键ctrl+r+e快速实现属性。)

Set 和Get的应用

一般面向对象编程语言都要求成员变量不能直接暴露给外部访问,如下:
public class A
{
public int Age; //这是不好的,待会有程序员可能把-1赋给Age
}
为了防止乱赋值,C#设计了一个属性机制,要求把成员变量设为私有,在通过属性来控制成员变量的读写,如下:
public class B
{
private int age; //私有成员字段
public int Age // age的属性,字段的属性名一般是把字段名首字母大写。此声明等同于public int Age(int value),value是隐含参数,只是不写出来。
{
get{ return age; } //读取器,当代码中调用属性时,启动get方法,在get方法中也可以写判断语句,赋值等,和set一样。在get里有判断的话,判断类中的字段。
set{ //写入器,当代码中给属性赋值时,调用set方法。在set中就判断value
if(value>0)
age = value; //value是准备写入的值
}
}
}
这样Age就像保安一样,挡在age的前面。访问age的时候需要通过Age许可,如下:
B b = new B();
b.Age = -1; //这是不行的,-1被带入value,value<0,判断不成立
b.Age = 10; //这是可行的,当给属性赋值时调用属性的set方法。把10传到Age属性的value隐形参数中,并且调用set方法。

Consloe.WriteLine(“请输入年龄{0}”,b.Age)//此时调用Age属性中的get方法,调用时只调用属性,不会直接调用私有化的字段

属性中set和get不是必须都需要的,但必须有其中一个。如果只有set方法就是只写属性,如果只有get方法,就是只读属性。

属性的作用就是保护字段、对字段的赋值和取值进行限定。

属性的本质就是两个方法,一个叫get()一个叫set()。

既有get()也有set()我们诚之为可读可写属性。

只有get()没有set()我们称之为只读属性

没有get()只有set()我们称之为只写属性

4、静态static和非静态

内存的区域:

栈:存储值类型,如Int,enum,struct

堆:存储引用类型,如string,interface,class ,arry,dynamic,object等。即在栈里只有一个指针,指针指向堆里的地址,所有的数据都存在堆里。

静态存储区域:存储静态类型。静态存储区域所有项目成员都可以访问,所以静态成员在整个项目中资源共享。且静态成员在代码编译时就分配了内存空间,而非静态成员只有在编译后才分配内存空间,所以静态成员无法调用非静态成员,因为非静成员有可能当时还没有生成。且只有当程序完成后才会释放空间。所以静态类型占用内存。

一般在你想做一个工具类时,即大家都会经常用到的类时,才会写成静态类。

非静态类中:

1)、在非静态类中,既可以有实例成员,也可以有静态成员。

2)、在调用实例成员的时候,需要使用对象名.实例成员;

在调用静态成员的时候,需要使用类名.静态成员名;

总结:静态成员必须使用类名去调用,而实例成员使用对象名调用。

静态函数中,只能访问静态成员,不允许访问实例成员。

实例函数中,既可以使用静态成员,也可以使用实例成员。

静态类中:

只能有静态成员,不能出现实例成员。

静态类不能被实例化。

5、构造函数

构造函数的作用是初始化类。

构造函数不能有返回值,连void也不行。

构造函数名和类名一样。

静态构造函数:

主要为类的静态字段进行初始化

一个类只能有一个静态构造函数,且不得带参数,不能有访问修饰符,如public。

6、析构函数

7、this

表示当前类的对象,类不占内存,但对象占内存。

只能用在:实例构造函数、实例方法以及属性和索引器的实例访问器。

8、partial部分类

在一个类中可以写两个完全相同的类,并且类与类之间的所有数据都可以共享,你就可以把他当成一个类,只是有两个地方。类名前加上关键字partial。

9、sealed密封类

不能够被其他类继承,但是可以继承于其他类。

Public sealed class preosn()

{};

七、继承

1、子类继承的内容:

(1)子类继承了父类的public字段、属性和方法,但是子类并没有继承父类的私有字段。

(2)子类不继承父类的构造函数,但调用父类的无参构造函数,以创建父类对象,以使子类可能使用父类中的成员。所以,如果在父类中重新写了一个有参数的构造函数之后,那个无参数的就被干掉了,子类就调用不到了,所以子类会报错。

解决办法:

在父类中重新写一个无参数的构造函数。

在子类中显示的调用父类的构造函数,使用关键字:base()

2、继承的特性

继承的单根性,一个子类只能有一个父类。

继承的传递性,从父类继承的内容,可以被自已的子类继承。

3、 object是所有类的基类

4、 语法:

Public class 类名:父类名 //注意,这里的修饰符要比父类的一致,或比父类的权限小,不能比父类的权限大。

5、 如果子类有与父类一样的方法,将隐藏父类的方法,即把父类覆盖了。

6、 要显示的隐藏父类中的方法,可以在子类的方法名前加关键字new.

7、子类的实例化对象可以赋值给父类的实例化对象。但父类的不能赋值给子类。

八、多态性

1、 虚函数

(1)语法

在基类中把虚函数加上关键字virtual,在子类中在函数前加上关键字override。

例:

Public class animal

{

Public virtual void test ()//基类中声明时加上关键字,声明成虚函数。

{

Console.writeline(“我是父类的”)

}

}

Public class cat:animal

{

Publicoverride void test()//子类中加上override重写虚函数。这里也可以不加,但不加的话就要加上关键字new,把父类的函数隐藏。即子类可以重写父类的虚方法,也可以不重写。

{

Console.writeline(“我是子类的”)

}

Animal aa=new cat(); //把子类对象赋值给父类对象。

aa.test();//调用子类中的test方法。执行过程如下:

程序执行到此处,跳转到父类的test函数上,但不执行父类的函数体,接着就跳到子类cat的 test函数上,并且执行函数体。 即此处aa对象赋的是哪个类的对象值,就执行哪个类中的虚函数。

(2)虚函数的作用

子类继承了虚函数后,子类可以重写虚函数,也可以不重写,实现多态性。

当父类的虚函数的实现也有作用时,用虚函数。子类继承了虚函数后重写虚函数。

虚函数就是用

(3)注意事项

子类中的虚函数要和父类的一致,即子类中的虚函数和父类中虚函数的返回值,类型,参数都要一致。

2、 抽象类

(1)语法:

父类:

public Abstract classanimal //在抽象类前面加上abstract关键字。

{

Public Abstract void test(int i); // 抽象方法前面也加上abstract关键字。修饰符不能是private。抽象方法是不能有方法体的,连大括号都不能有。所有的抽象成员在子类中必须被重写。

Public void sum()//抽象类中允许有非抽象方法和非抽象字段,属性。

{ }

}

Animal dog=new animal(); //这是错误的,抽象类是不能被实例化的。

子类:

Public class cat:animal

{

Public Override void test(int j) //子类中用override重写抽象方法,且父类中的所有抽象成员必须在子类中重写。

{ }

public Override num() //这种写法是错的,抽象方法只能出现在抽象类中。除非子类也是抽象类。

{ }

}

(2)注意事项:

1.抽象成员必须标记为abstract,并且不能有任何实现。

2.抽象成员必须在抽象类中。

3.抽象类不能被实例化

4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。

(除非子类也是一个抽象类,则可以不重写)

5.抽象成员的访问修饰符不能是private

6.在抽象类中可以包含实例成员。

并且抽象类的实例成员可以不被子类实现

7.抽象类是有构造函数的。虽然不能被实例化。

8、子类重写父类的虚函数时,必须与父类一致,即返回值类型,参数及参数类型都要保持一致。

--------------------------------------------------------------------------------------------------------------------------------

如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。

如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。

3、 接口

(1)语法:

Public interface ikoulan

{

Void koulan(); //接口中的函数和抽象函数一样,不能有方法体。继承接口的子类,必须实现接口中的所有成员。接口不能被实例化。前面不能加修饰符,默认是public.

String daqui(); //接口中只能有方法、属性、索引器、事件成员,不能有构造函数和字段。

}

Public class prson:ikoulan

{

Public void koulan() //这是prson类已有的函数。当人类里面已有一个koulan函数时,就要另外显示的实现接口函数,在函数前加上接口名。

{

}

Void ikoulan:koulan() //一定要实现接口中的成员。因为子类中已有相同名的函数名,所以在这里显示的加上接口名。如没有得复不用加接口名。

{

Console.writeline(“高个可以扣篮”);

}

}

在main函数中:

Ikoulan test=new prson(); //接口不可以实例化,但是可以把子类的对像赋值给接口对象。

(2)用法

当想多继承时,就需要用到接口,因为类是单继承的,只能用接口来实现多继承。

接口就是一种规范,能力。

接口与接口之间可以继承,并且可以多继承,即一个接口可以继承多个接口。

接口并不能去继承一个类,而类可以继承接口 (接口只能继承于接口,而类既可以继承接口,也可以继承类)

当几个类提取不出来一个父类,但有一个共同的行为时,用接口。

当几个类能提取出一个父类,且有这几个子类都必须执行的方法,但是不知道这方法怎么实现时,就用抽象类,实现多态性。

当几个类能提取出一个父类,且有这几个子类都必须执行的方法,且知道怎么实现这个方法,还想实例化父类时,就用虚函数实现多态性。

(3)注意事项。

八、集合与泛型

很多数据的集合,和数组类似。

数组长度不可变,类型单一。

集合的长度可以任意改变,类型随便。

1、 Arraylist

方法:

(1)ADD方法:把单个元素添加到集合中。

ArrayList list=new ArrayList();

List.Add(1); //添加整型数据到List集合

List.Add(“张三”); //添加字符串到List集合

List.Add(new int[]{1,2,3,4,5}); //添加数组到List集合。此时如果遍历List时,会显示数组的命名空间名字,而不会显示数组中的元素。要解决这个问题,要用addrange方法。

(2)AddRange方法用于添加一批元素到当前列表的末尾

List.AddRange(new int[]{1,2,3,4,5}); //添加数组到List集合。

List.AddRange(list); //把自已添加到自已的集合里面。

(3)Remove方法用于删除单个元素,通过元素本身的引用来删除

List.Remove(“张三”); //写谁就删谁。

(4)RemoveAt方法用于删除一个元素,通过索引值来删除,即下标。
List.RemoveAt(0); //会删除List.Add(1)中的1,他是第List中的第一个元素。

(5)RemoveRange用于删除一批元素,通过指定开始的索引和删除的数量来删除

List.RemoveRange(0,3); //删除list中第1个元素开始后的三个元素。

(6)Insert在指定的索引位置插入元素,列表后面的元素依次往后移动

List.Inset(3,“李四”); //在第4个元素后插入字符串李四。

(7)InsertRange在指定的索引位置插入一批元素(在集合中插入集合),列表后面的元素依次往后移动

List.InsetRange(1,new string[]{“王五”,赵六”,”李七”}); //在第2个元素后插入字符串数组。

(8)Clear方法用于清除现有所有的元素

(9)Contains方法用来查找某个对象在不在列表之中,即判断集合中是否包含指定的元素。

Bool a=list.contains(“李七”); 是否包含李七,包含为1,不包含为0,即假。

(10) sort升序排列集合,但要求集合中的元素的类型基本一致才可行。

(11) count:表示集合中实际包含的元素的个数

(12) capacity:集合中可以包含的元素的个数。当实际包含的元素个数超过可包含的元素个数时,集合会向内存中申请多开辟一倍的空间来保证集合的长度一直够用。

(13)遍历arraylist集合:

For(i=0;i<list.count;i++) //list.count表示集合的长度

{

Console.writeline(list[i]);

}

2、hashtable 键值对集合,类似于字典,根据键找到值,键和值一一对应。

(1) 方法:

Hashtable ht=new hashtable();

Ht.Add(1,”张三”); //添加值到集合中

Ht.Add(2,”李四”);

Ht.Add(false,”错误”); //键是false

Ht[true]=”正确”; //也可以通过赋值方法来添加元素到集合中。

Console.writeline(ht[1]); //打印出键为1的值,会显示出张三。

Ht.clear(); //清除所有元素

Ht.remove(3); //根据键来清除单个元素。

(2)遍历集合

Foreach(var item in htlist) //用foreach循环来遍历hashtable集合。

Foreach(var item in ht.keys) //keys属性是指hashtable集合的键,即遍历整个集合的键

{

Console.writeline(“键是{0},值是{1}”,item,ht[item]); //同时显示键和值。Item代表了键,而ht[item]代表了每个键对应的值。

}

(3)键值对集合中键必须唯一

键值对集合中,键必须是唯一的,值可以重复。所以添加元素到集合中时,先判断键是否已存在。

If(ht.containsky(“true”)) //如果ht集合中已包含键true。

3、 list泛型集合

(1)泛型集合的要点:

要指定集合的类型,集合中的元素都要是这个类型的。

与arraylist的不同之处就是要指定元素的类型,其他方法基本一样。

List泛型集合可以转换成数组,数组也可以转换成集合。

(2)建立list集合对象:

List<int> list=new list <int>(); //声明一个List集合,<>号中指定元素的类型。

(3)集合转数组和数组转集合

Int[] num=List.toarray(); //用toarray方法把list集合转换成数组,转换成什么类型的数组取决于你是什么类型的集合。

Char[]chs =new char[]{‘a’,’b’,’c’};

List<char>listchar=chs.ToList(); //用ToList方法把数组转换成集合。

4、 字典集合

(1)字典集合的要点:

与hashtable集合使用方法完全一致,只是键和值指定了类型

键也必须是唯一的

(2)建立字典集合对象

Dictionary<int,string>dic=newDictionary<int,string>();

(3)两种遍历方法

方法一:

Foreach(var item in dic.keys)

{

Console.wirteline(“键是{0},值是{1}”,item,dic[item]);

}

方法二:

Foreach(keyValuePair<int,string>kv in dic) //keyvaluepair表示键值对,既表示键也表示值,所以这种方法可以让键和值一起显示。

{

console.writeline(“键是{0},值是{1}”,kv.key,kv.value);

}

九、转换

1、装箱、拆箱

装箱:将值类型转换成引用类型。

拆箱:把引用类型转换成值类型。

2、里氏转换

(1)子类可以赋值给父类。

父类:

Public class person

{

Publicvoid sayhello()

{

Console.writeline(“我是中国人”);

}

}

子类一:

Public class hubie:person

{

Publicvoid sayhello()

{

Console.writeline(“我是湖北人”);

}

}

子类二:

Public class jiangsu:person

{

Publicvoid sayhello()

{

Console.writeline(“我是江苏人”);

}

主函数:

Person china=new hubei(); //把子类对象赋值给父类。如果有一个地方需要父类作为参数,可以用一个子类对象代替。

(2)如果父类中装的是子类对象,可以将这个父类强转为子类。

jiangsu js = (jiangsu)china; //父类对象中装的是哪一个子类成员,才能转换成哪个子类的。这里的父类对象china前面被赋的值是hubei子类的,所以要强转成jiangsu子类的,会出错。

hubie hb = (hubie)china;//这个会成功。

(3)IS

if (china isjiangsu)//is的作用是,如果转换目标成功,则返回一个true.先判断再转,避免拋异常。

{

jiangsu js = (jiangsu)china;

}

else

{

Console.WriteLine("转换失败");

}

(4)AS

jiangsu js1 = china asjiangsu;//作用是,如果转换成功就继续执行,如果不成功刚返回值null。不会拋异常。这里js1的值就会是null.

十、委托

十一、反射

第二部分:文件、目录及文件流的操作

文件的操作

1、 创建文件

File.create(@”c:\test\test.txt”).close(); //@是去除转义符。建好后就关闭,否则如果后面要写入内容就会出错。

2、 删除文件

File.Delete(@”c:\test\test.txt”);

3、 复制文件

File.Copy(@”C:\test\test.txt”,@”c:\test\new.txt”); //复制文件并更名。

4、 移动文件或重命名

File.Move(@"d:\site\file\test7.txt", @"D:\site\file\newfile\test7.txt");

5、判断

if(File.Exists(@"d:\site\file\my.txt")) //判断文件是否存在,如果存在先删除再建立。不存在,直接建立。

{

File.Delete(@"d:\site\file\my.txt");

File.Create(@"d:\site\file\my.txt").close();

}

else

{

File.Create(@"d:\site\file\my.txt").close();

}

6、读取文件

(1) File.ReadAllText(path); //读取文件中的内容,但把所读到的所有内容当一个字符串处理。返回值是字符串,不是字符串数组和集合。

(2) File.ReadAllLines(path);//读取文件中的内容,但把每一行当一个字符串,返回值是一个字符串数组。

7、写入数据 //写入数据会覆盖原有的数据

(1)File.WriteAllLines(path,string[]); //path是文件路径,string[]是要写入的字符串数组,一定要是数组。

(2)File.WriteAllText(path, string); //path是文件路径,string是要写入的字符串。

8、追加数据 //追加数据是添加在后面,不会覆盖原有数据。

(1)File.AppendAllLines(path,string[]); //path是文件路径,string[]是要写入的字符串数组,一定要是数组。

(2)File.AppendAllText(path,string); //path是文件路径,string是要写入的字符串。

9、设定文件属性

File.SetAttributes(path,FileAttributes.ReadOnly);//可以设置文件属性为只读,可写,隐藏等。

10、综合例:

staticvoid Main(string[] args)

{

string path = @"d:\site\file\my.txt"; //把常用的路径定义成一个字符串。

string all = ""; //为遍历字符串拼接字符串赋一个空字符串。一定要先赋值。

if(File.Exists(@"d:\site\file\my.txt")) //如果文件存则为真,不存在为假

{

File.Delete(@"d:\site\file\my.txt");

File.Create(@"d:\site\file\my.txt").Close();//文件如存在,就先删掉此文件,马上再建一个,建好后马上关闭。

}

else

{

File.Create(@"d:\site\file\my.txt").Close();//如果文件不存在就直接建一个。

}

string test= File.ReadAllText(@"d:\site\file\test.txt",Encoding.Default);

//读取另一个文件中的内容,存为一个字符串。

string[] test1 = File.ReadAllLines(@"d:\site\file\test.txt", Encoding.Default); //读取另一个文件中的内容,存为一个字符串数组。

File.AppendAllLines(path, test1); //把字符串数组作为内容添加到path路径所指文件中,即my.txt中。如此时把test1换成test会报错,因为test只是一个字符串,不是一个数组.

File.AppendAllText(path, test); //把字符串添加到my.txt中。

File.AppendAllText(path, "我是一个北方的狼");

string[] s = File.ReadAllLines(@"d:\site\file\my.txt"); //读取my.txt中的内容,并赋值给一个字符串数组。

foreach (var item in s) //遍历字符串数组

{

all += item.ToString(); //把字符串数组拼接成一个字符串。

}

//File.WriteAllLines(@"d:\site\file\test1.txt",s); //把字符串数组的内容写入test1.txt中,原来的文件内容会被覆盖。

//File.WriteAllText(@"d:\site\file\test.txt","我会覆盖你原来的内容");//把字符串的内容写入test1.txt中,原来的文件内容会被覆盖

Console.WriteLine(all);

Console.ReadKey();

}

目录操作

1、path类(路径的操作)

String str=@”d:\site\loready\p_w_picpath\3.jpg”;

Console.writeline(Path.GetFileName(str)); //获取路径中的文件名,显示为3.jpg

Console.writeline(Path.GetFileNameWithoutExtension(str));//获取文件名,但不包含拄展名,显示为3。

Console.writeline(Path.GetExtension(str)); //获取扩展名,显示为jpg

Console.writeline(Path.GetDirectoryName(str)); //获取文件夹的名称,显示为d:\site\loready\p_w_picpath

Console.writeline(Path.GetFullPath(str)); //获取全目录,即显示为d:\site\loready\p_w_picpath\3.jpg

Console.writeline(Path.Combine(@”c:\a\”,”b.txt”)); //连接两个字符串作为路径,显示为c:\a\b.txt

其他方法见MSDN。

2、目录的操作

Directory类

Directory.Delete(@"d:\site\file\file_dir”) //删除一个目录

Directory.Move(@"d:\site\file\file_dir1",@"d:\site\file\file_dir");//移动一个目录到另一个目录,前面是源目录,后面是目的目录路径

if(Directory.Exists(@"d:\site\file\file_dir"))//判断目录是否存在

{

string[]s=Directory.GetFiles(@"d:\site\file\file_dir");

//getfiles是获取目录下的文件及路径。

for (inti = 0; i < s.Length; i++)

{

dir += s[i];

}

}

else

{

Directory.CreateDirectory(@"d:\site\file\file_dir");//创建一个目录

}

Console.WriteLine(dir);

Console.ReadKey();

要想复制目录,思路是用递归的方法遍历源目录下的所有目录及文件,把这些目录和文件再复制到另一个地方。

文件流操作(用于操作大文件)

把大文件碎片化操作,一块一块操作,而FILE类,则是文件一次性操作。

1、 Filestream(操作字节的,任何文件都可以操作)

(1)读取数据

FileStream fs=newFileStream(@"d:\site\file\test.txt",FileMode.OpenOrCreate, FileAccess.Read);//第一个参数是要操作文件的路径;第二个参数是对文件的操作模式,是打开(Open),创建(Create),还是追加(Append),OpenOrCreate是如果文件不存在就创建并打开,如果文件存在就直接打开;第三个参数是对文件里的数据进行的操作,是读(fileaccess.read),还是写(fileaccess.write)。

byte[] buffer=newbyte[1024*1024*1];//建立一个字节数组,并指定一次性读取文件的大小,这里为1M。

int r=fs.Read(buffer, 0, buffer.Length); //第一个参数是指把读取到的内容存到buffer字节数组中,第二个参数是从哪里开始写入数据,0即是开始位置,buffer.length即表示每次最多读取数据的大小,即1M。返回的int类型值,是指读取到的字节数。

string s = Encoding.Default.GetString(buffer,0,r); //把存放在字节数组中的数据流解码成字符串。0是从流的0位置开始解码,r是指解码的字节数。这样就会只解码刚才读的部分。

fs.Close(); //c#无法自动释放数据流,所以要先关闭数据流,再用dispose()释放流。

fs.Dispose();

Console.WriteLine(s);

(2)写入数据

using (FileStream fswrite = newFileStream(@"d:\site\file\test.txt", FileMode.OpenOrCreate, FileAccess.Write)) //using中会自动释放流的资源。此处最后一个参数改成了写的状态。

{

string w = "我们的家在松花家上啊,那里有大豆高粱";

byte[] buffer1 = Encoding.Default.GetBytes(w);//把要写入的字符先转换成数据流,然后存入buffer1字节数组中。

fswrite.Write(buffer1,0,buffer1.Length); //第一个参数是字符数组,第二个参数是从哪里写入,第三个参数是写入的最大长度。

Console.WriteLine("写入OK");

Console.ReadKey();

2、 streamreader和streamwriter(操作字符的,即文本文件)

每次只读文本中的一行,要读完就要循环到文本的最后一行。

读:

Using(streamreader sr=new streamreader(@”d:\site\file\test.txt”,encoding.default)

{

While(!sr.endofstream) //如果没读到文本的行尾

{

Console.writeline(sr.readline());//就不停的读下一行并显示出来。

}

}

写:

Using(streamwriter sw=new streamwrite(@”d:\site\file\test.txt”,true) //true表示追加到原文本后面,不会覆盖原文本。

{

Sw.write(“要写入的字符”);

}

第三部分:字符串操作、编码及正则表达式

一、字符串操作

字符串是引用类型且字符串对象是不可变的:即它们创建之后就无法更改,不能依据其堆中的存储地址找到它然后更改它。

如:string s=”123”;此时s在栈中指向堆中123的地址空间。

string s=”456”;此时对S重新赋值,但不会像其他类型一样,456会存到123原有的地址空间,替换掉123,而是在堆中重新开辟一个空间存值 456,且把s在栈中指向的地址改向456的地址。原来123在堆中仍然存在,并没有消失。

示例:

字符串的下标索引位是从0位开始。

String s=”abc_def” //声明字符串

String b=”efg”

1、 计算字符串

s.Length //字符串长度,返回的是整数。

2、 截取字符串

s.Substring(start,end) //从字符串的第几位到开始到第几位结束间的所有字符串,可以只有start或只有end。从0位开始计算。

Cosole.writeline(s.substring(1,5)); //显示结果为:bc_de

3、 分割字符串

s.Split(“分隔符”)//用分隔符把字符串分成多个字符串,返回字符串数组

string[] test=s.split(‘_’); //把s字符串用_分成两个字符串,即字符串组,注意是单引号。

console.writeline(test[0]); //显示为abc

console.writeline(test[1]); //显示为def

4、 替换字符串

s.replace(“source_string”,”replace_string”) //用后面的字符串替换掉前面的字符串。

console.writeline(“abc”,”ABC”); //显示为ABC_def

5、 比较字符串

s.Equals(b) //比较两个字符串是否相同,如果相同则返回ture,否则返回false。S字符串和b字符串不一样,所以返回值为ture。

6、 转换字符串

s.ToLower() //把字符串转换成小写

s.ToUpper() //把字符串转换成大写

7、 插入和删除字符串

(1)s.Insert(start,”要插入的字符串”); //从第几位开始把后面的字符串插入到字符串中。

(2)s.Remove(start,end)//删除字符串中从start位开始到end位结束的字符。可以只有start或只有end。

console.writeline(s.insert(4,b); //显示为 abc_efgdef ,从第四位开始插入字符串b变量中的内容。

8、 匹配索引和包含判断

s.IndexOf(“bc”)// 从字符串头部开始搜索第一个匹配“bc”的在字符串中的位置索引。如果没有匹配,输出为-1。此如出显示出来,索引值为1,bc的开始下标为1开始。

s.Lastindexof(“de”)//从字符串尾部开始搜索第一个匹配“de”的位置索引。此处如显示出来,索引值为4。

s.Contains("def")//判断字符串中是否包含字符串"def",有输出ture,没有输出false.此处返回为ture。

9、 连接字符串

string[] arr = s.Split(‘_’); //把字符串s用下划线分隔成两个字符串。这里是单引号。

此时arr[0]=”abc”;

Arr[1]=”def”;

(1)String.Join(“分隔符”,字符串数组名) //把一个字符串数组连成一个字符串,用分隔符隔开。

Join(“分隔符”,字符串,字符串,字符串……) //把字符串连接成一个字符串,用分隔符隔开。

(2)String.Concat(字符串数组名) //把字符串数组,连成一个字符串。

String.Concat(字符串,字符串,…..) //把字符串连成一个字符串。

例:

String s=”abc_def”

string[]arr = s.Split('_');//分割成两个字符串

stringtest=string.Join(",",arr);//用分隔符逗号把arr字符串数组中的字符串连接到一起。

Console.WriteLine(test); //显示为abc,def

Console.WriteLine(string.Concat("qf","ef",”mf”));//显示为gfefmf

Console.ReadKey();

Join和concat的区别,只是一个有分隔符,一个没有。

(3)StringBuilder类

StringBuilder sb =newStringBuilder(); //定义一个类对象。

sb.Append(s); //把字符串变量s中的内容添加到sb对象中。

sb.Append(b); //把字符串变量b中的内容添加到sb对象中。

Console.writeline(sb.tostring()); //再把sb对象转换成字符串输出显示为abc_defefg

二、字符编码

编码:将字符串用怎样的形式保存为二进制。

Asc:128 主要是美国用,英文和数字。

Ascii: 256欧州用

Gb2312国标,中国用,简体字

Big5繁体字

Unicode很全,世界上的编码都包含,全世界都能用,但太大了,会慢。

Utf-8世界通用,主要用于web。