第一部分 重点基础
基础部分
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\n windows系统的换行
\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 catch finally
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 class animal //在抽象类前面加上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。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。