命名空间:
格式:namespace 空间名 {}
作用:建立一个可以使用的空间。
注意:空间需要包括一个类。
嵌套的命名空间:
定义:有相同的空间名,但类名不同的空间。
例:Sony(空间名)下有TV和Walkman 2个类。
注意:不允许在另一个嵌套的空间中声明多部分的命名空间,命名空间与程序集无关,同一个程序集中可以用不同的命名空间。
空间别名:
格式:Using 别名(自定义名称)= 空间名的连接地址
例:Using STV = Sony(空间名).TV(类名)
注意:空间名和类名之间用 . 来表示。
标识(@):
功能:用来区分自定义名和系统内关键字。
定义:程序中有77个无法使用的关键字:如“int”“namespace”等,如果一定需要使用这些关键字来命名的,则需要在这些关键字前加上@.
变量:
格式:变量类型 自定义变量名 = 自定义内容
注意:等式2边的类型必须相同。
变量类型:
变量分为 数值型 和 非数值型 。
数值型又分为整型(整数) 和 非整型(带小数点)
整型的变量有:int , short int(短整型) long int(长整型)
非整型的变量有: float, double
非数值型的变量有: char , string , bool
变量类型的细分:
String 字符型:
格式:string 变量名 = “内容”;
注意:“”内表示的是一串字符。
Char型:
格式:char 变量名 = ‘内容’;
注意: ‘ ’ 内表示的是一个字符。
Bool 布尔型:
格式:bool 变量名= true 或 false;
注意:布尔型只能用true和false来表示其内容。
Int 数值型:
格式:int 变量名 = 数值(整数);
注意:int只能用整数来表示其内容。
Double 型:
格式: double 变量名 = 数值(整数和小数点);
注意: double 可以用整数或小数点来表示其内容。
类型的转换:
转换模式:隐式:不会造成丢失的显示转换。
例:long a=int b; 因为long类型范围大于int类型范围,所以把int类型的值赋予long类型的值不会造成丢失。这样的转换叫做隐式。
显式:会造成丢失的显示转换。
Convert 强制转换命令:
功能:实现各类型之间强制转换。
格式:Convert . 需要转换的类型(需要转换类型的内容或表达式);
类型的转换实例:
Int 类型转换 string a= “13”; int b =int.Parse(a); 或 int b = Convert.ToInt32(a);
完成字符型转换成数值型
int . Parse 此关键字只能使用在string型和int型之间的转换
Char a = ‘!’; int b = (int) a; 或 int b = Convert.ToInt32 (a);
完成char型转换成数值型。
此表达式char型代表一个字符,故转换数值型后,则表示字符所代表的AscII码。
Char型转换 char a = ‘A’; bool b = char.IsUpper (a);
完成char型转换成bool型。
char.IsUpper用AscII码来判断大小写。这时变量b的值,只能是true或false.
char a = ‘A’; char b = char . ToLower(a);
char . ToLower表示强制把字符A转换成小写字符。
bool型的判断符:= = 表示是否相等 !=表示是否不相等 | | 表示或者
&&表示同时满足 >表示大于 <表示小于 >=表示大于等于 <=表示小于等于
三元运算符:
格式:变量类型 变量名= bool判断式 ? 判断后true的显示内容 : 判断后false的显示内容
Bool判断式表示方式: a= =1 等。变量类型必须和显示内容的类型相同
Int型的组合赋值:
Int sum = 10;
在循环里如果要给变量sum +40,然后再继续使用+完后的结果时,则表示为sum=sum+40;因为系统会有优先级,先计算sum+40,然后再赋值给sum。 简写为:
sum+=40; 一般用来表示连续数字的累加求和。
Substring 字符的索引表示方法:
格式:Substring (字符串的第几位 , 从第几位开始取几位数字);
回文数字的判断:
像12321这样的数字称为回文数字;要判断一串数字是否是回文数字时可以使用
索引表示方法来判断:
Substring 是string型的,字符串的索引是从第0位开始的(实际字符串的第1位)
12321的实际字符串的第一位是1,索引的表示方法则是第0位。要单独取一个1这1个字符,索引的表示方法为:Substring (0,1)
用以上的方式可以单独取出12321里的4个单独的字符:
第一个1 :String a1 = Substring( 0 , 1 ); 第2个2:String a2 = Substring( 1 ,1 );
第4个2 :String a3 = Substring( 3 , 1 ) 第5个1:String a4 = Substring( 4 , 1 )
然后用a1和a4进行判断,a2和a3进行判断,如果都相等则表示这样的一串数字是回文数字。
++自增张的表示:
格式:++变量名 或 变量名++
区别功能:++变量名表示:表达式和变量自身都+1;
变量名++表示:表达式无变化,变量自身+1;
例:
int I=1; int a=++I;
先执行I自身+1,I=2, 然后表达式再执行a=I,所以a=2;
显示结果为:a=2; I=2;(表达式和自身都+1)
int I=1; int a=I++;
先执行 a=I,这时I=1,所以a=1,然后在执行I的自身+1,I=2;
显示结果为:a=1,I=2;(表达式无变换,自身+1)
方法:
定义:作为一个可以去遵循的公式,用于计算和处理整个程序的运行。所有的方法都可以看作是一个套入的公式,并随时可以调用。
格式: (访问修饰符可以没有) 变量类型 方法名(参数类型 参数名《可以没有参数》){}
返回类型方法:
定义: 操作和运行此方法需要得到一个值或得到一个结果。
格式:变量类型 方法名(参数类型 参数名){return 操作方式或结果 ;}
无返回类型方法:
定义:只需要执行此方法,并不需要得到结果。
格式: void 方法名(可以没有参数){}
执行方法:变量类型(可以省略) 方法名(参数名);
注意:只有void是无返回类型的方法,其他变量类型都是返回类型,变量类型必须和参数类型一致,方法是直接放在类下的,所以和Main函数和事件是平级的。
事件:双击一个空间按钮就叫做事件。
方法的重载:
定义:在同一类下,2个方法的方法名相同,但2个方法的参数类型或参数个数不同,这样的2个方法叫做方法的重载。
例:int mj(int a){return a*3.14;}
Int mj(int a,int b){return a*b;}
注意:方法的重载必须是方法名相同,但参数类型不同或者参数个数不同才能实现。也就是说只能根据方法的参数类型和参数个数来判断是否是重载。
显示命令:
Console.WriteLine();
表示:把需要显示的内容用string型来显示并完成自动换行,显示完后光标会停在下一行里。
Console.Write();
表示:把需要显示的内容用char型(一个一个字符)来显示,只会在同行内显示,显示完后光标会停在同一行里。
Console.ReadLine();
表示:让需要显示的内容长时间停留不被自动关闭(strin型)
Console.Read();
表示:让需要显示的内容长时间停留不被自动关闭,但使用此命令显示int型时会显示int型值的AscII码。(char 型)
“\n”强制换行命令:
格式:Console.WriteLine(“内容:内容 \n 内容 :内容”);
如果显示内容里需要有 “”表示的,则表达式为:\“内容\”
占位符{0}:
格式: “{0}:内容 = {1}”,a,b
占位符表达填空内容,a,b的值会在对应的占位符内显示。
数值的格式化:
格式:{0:代码}
例:{0:f2},则表示显示的值后面需要保留2个小数点。
其他的代码查help.
多重if语句:
功能:表达如果形式的代码执行方式。
格式:if(表达式) {执行}
else if(表达式){执行}
嵌套if语句:
格式:if(表达式){if(表达式)if(表达式){执行}}
else {执行}
注意:else总是属于离的最近的if,一般在分支不多的情况下使用if语句。
Switch 语句:
功能:和if一样也是表达如果形式的代码执行方式。
格式:switch (变量名)此变量只能是int或string类型
{case值1:执行代码
break;
case值2:执行代码
break;
default:执行代码(可以省略default)}
寻找并执行满足case值的命令,如果变量都不能满足case的值则去执行default里的代码。
注意:switch的变量类型和case值的类型必须是同一类型,case值必须为常量。
While 语句:
功能:循环执行符合条件的代码,直到超出条件范围停止循环。
格式:while(判断表达式){执行代码}
注意:只要执行内容超过或不同于判断表达式,才跳出循环,所以需要有一个哨兵变量,不然就为死循环
哨兵变量:I++;
do while 语句:
功能:同while。
格式:do{执行代码}while(判断表达式)
注意:程序走到do命令时,先执行一次do{}的代码,然后去判断whlie内容,满足的则继续执行,不满足则不再执行。
区别:do while 先执行再判断,不管是否满足条件都会去执行一次;
while 先判断再执行,不满足条件不会去执行。
For 语句:
功能:同while。
格式:for(变量声明;条件表达式;哨兵变量)
注意:变量声明必须是表达式,如果一定要使用过的变量名,也必须再给变量赋值,即a=a;如果已经声明过变量,声明变量可以为空,但分号不能少。
跳转语句:
Continue;
功能:遇到后,不去执行后面的代码,直接返回重新去判断,直到不满足条件为止,表示跳出本次循环。
break;
功能:遇到后,跳出整个循环。
异常的操作:
异常:Exception是一个对象(类),所以异常都属于它;
格式:try{可能或已经出现异常的代码}catch(Exception 自定义名){执行操作}
可以有多个catch。
检测数据是否溢出:
溢出:数据内容超出指定的范围。
格式:checked{可能出现溢出的代码}
也可以用表达式:checked(可能出现溢出的表达式)
unchecked{} (表示不需要检测的代码,一般在try下使用)
人为定义一个异常:
功能:先把需要抛出的代码设定为异常。让try进行处理。
格式:throw new 异常类型《一般情况下用Exception》(定义异常的属性内容可以理解为出现异常告知用户的内容)
注意:抛出异常是从最底层,一层一层往上抛的,抛出了异常就必须在(最上层)进行捕获。
封装(概念):
类:是思想上认为的。(把所有有共性的东西,归为一类)
对象:是真是存在的。(对象是这个类的一个实例)
面向对象的三大特征:封装,多态,继承。
面向对象的优点:
封装(代码):
功能:把数据与方法放在同一个单元里(类)
创建对象:
格式:已创建的类名 自定义对象名 = new 已创建的类名(实例化的内容《可以省略》);
访问修饰符:
Public:把数据定义为公共的,在外部也可以使用。
Private:把数据定义为私有的,只有在同一类能使用,外部是无法访问的。
Proteceted:把数据定义为继承的,只有有亲缘关系的类才能使用,其他类无法使用。
(无法和系统生成的类建立继承,所以在Main函数下也无法使用其他类中带有proteceted访问修饰符的内容。)
Internal:
构造函数(方法):
功能:用来初始化变量的一种方法。
格式:public 所在类或结构的名字(需要初始化变量的类型 自定义变量名《也可以没有这些内容》)
{ 需要初始化的变量名 = 自定义变量名 《也可以没有这些内容》}
注意:{ }内不能有返回类型return。
?(需要请教老师)
partial类:
功能:实现在不同类文件中调用已经存在的类里的内容。
格式:partial class 需要使用的类名{}
注意:加上partial的那些类,表示为同一类。
const 常量(静态类关键字)(静态的,不能和static关键字一起使用)
格式:const int x = 100;
作用:声明一个永远不变的量。
静态构造函数:
典型用途:使用日志文件时向日志文件写入项,在为非托管代码创建包装类时也很有用。
格式:public static 类名或结构名(){}
注意:声明的时候必须赋值,并且不能更改的值,也不能用构造函数初始化值。静态构造函数:没有访问修饰符,也没有参数,没有返回类型,无法直接调用,无法控制何时执行。
static (静态关键字)
格式:static class类名或类型;
作用:需要经常重复使用的内容会使用static。
注意:里面的所有成员都是静态的,都需要加上static关键字,是密封且不可继承的。有了static关键字,可以不用用new命令生成对象调用,可以在其他类里直接用类名加.(点)的方式调用此对象。
值类型与引用类型
值类型:2个人拿到了2份结果,自己处修改后不会影响到另一个人的结果。
通俗的表达方式:a=40,b=40.40为值,只是把40这个值复制给了对方,a和b任何一方发生了改变都不会影响到另一方。
引用类型: 2个人只是拿到同一个地址(例如:拿到了钥匙),但地址内的结果被修改了,那同时影响了地址。
通俗的表达方式:a=40=b; 40为值,如果值发生改变,则a和b都发生改变,也可以认为a和b还有值这3方只要有1方发生改变,另2方也随之改变。
*基本类型中除了string,其余都是值类型*。
参数
函数参数表中是若干个变量定义,这些变量叫做形参。
调用函数的时候把实际的数据传递个函数的形参,这些实际的参数叫做实参。
ref 参数(引用修饰符)
加了ref 把值的传递方式变成了引用的传递方式,原本是直接给他值现在改变为只给了地址。
参数前加上ref修饰符,参数就成为引用型参数;引用型参数是实参所代表变量的别名或者说引用型参数与实参指向了同一个对象;
ref修饰符必须同时出现在函数声明和函数调用语句中。
ref参数的实参*必须*被预先赋值
ref参数的实参必须是变量型的,而不是纯粹的值或常量。
ref无法直接给予赋值 例: int i; fun(ref 42);
static void fun(ref int param)
{param++}
这个方法表示把I的值得用引用的方法传递给param。这样的操作是错误的,无法直接给i进行赋值得,必须给i先赋个值 需要加i=42.
正确的方法是 int i=42; fun(ref i);
out 参数(修饰符)
参数前加上out修饰符,该参数就是成为out型参数,out型参数是实参所代表变量的别名或者说out型参数与实参指向了同一个对象:
函数内部对该参数所做的修改都会反映到实参所代表的变量中。
out修饰符必须同时出现在函数声明和函数调用语句中。
out参数的实参*不必*被预先赋值
out参数的实参必须是变量型的,而不是纯粹的值或常量。
计算机内存分为堆和栈:
栈又叫做堆栈。
调用一个方法时,方法的参数和局部变量所需要的内存都从栈上申请。方法执行完毕,方法的参数和局部变量所需要的内存又自动释放回栈中,并可以被其他方法使用。
当你使用new关键字和构造函数创建一个对象,创建对象所需要的内存直接从堆上申请。当然一个对象可以被多个引用变量引用
当最后一个引用变量消失的时候,对象使用的内存就标记为可以重用。
*所有值类型都在栈上,变量地址也是存放在栈上。*
*所有引用类型都在堆上。*
装箱操作:把值类型转换为引用类型称为装箱操作。
因为值类型是在栈里,而引用类型是在堆里,所以先把值类型的值从栈里拷贝到堆里
面,然后从堆里面把地址再拷贝一份到栈里面,这样的一个过程叫做装箱操作。(装箱的值是不会改变的)
拆箱操作:把引用类型转换为值类型称为拆箱操作。
因为引用类型是在堆里,而值类型是在栈里,所以先建立堆里的引用类型到拷贝栈里面的地址,然后再在堆里的引用类型的值拷贝到栈里
。还必须要把引用类型强制转换成值类型。这样的一个过程叫做拆箱操作。
拆箱会出现异常:会抛出个异常类。异常类为“InvalidCastException”
枚举:
功能:用枚举可以节约性能。
格式: enum 枚举的名字{ 内容 }
显示: 枚举的名字 . 内容
*枚举必须和类平级*
结构构造函数和类构造函数的区别:
结构(struct)是值类型的(轻量级)。其值是可以拷贝的。存放在栈上,结构的构造函数必须有有参数,如要生成没有参数的结构函数只能是系统来生成的缺省结构函数,自己无法生成,结构的构造函数不会自动初始化字段,
格式: public 结构名(参数) { 需要初始化的变量 }
构造函数名必须和结构名相同
类(Class)是引用类型的(重量级),其值是不能拷贝的,拷贝的是引用(地址)。存放在堆上,类的构造函数可以没有参数(类名()),系统不会自动生成缺省结构函数,类的构造函数会自动初始化字段,
格式: public类名(参数) { 需要初始化的变量 }
构造函数名必须和类名相同
数组(Array)(只是一个容器):
表示:类型[ ]
数组内所有的变量或常量称为数组的元素。
数组是可以在内存中连续存储多个元素的结构。
数组中的所有元素必须属于相同的数据类型
数组的的元素的类型可以为任何类型,也可以是枚举,类或结构,也可以包含数组。
数组的内空间的排序是按照索引进行排序的。(初始的第一位数为0开始)如果要输出容器内的定义的几个空间里的内容,就需要先找到空间里内容的位置,所以需要用索引的办法来寻找。
数组的大小可以为0,这样的数组并非null数组。
声明(定义)数组:
格式:需要声明数组的类型[ ] 数组名称=new 数组的类型[ 空间个数] {需要存放的个数(必须和空间个数相等)}
也可以:需要声明数组的类型[ ] 数组名称= { 需要存放的值 }
以上种方式表示不确定数组有多少空间个数
还可以:需要声明数组的类型[ ] 数组名称=new需要声明数组的类型[ 空间个数 ];
以上方式表示不确定数组空间里的内容
数组的输出需要用索引方式输出
格式:数组的名称[索引的位数从0开始计算]
foreach 数组循环命令
作用:实现显示数组空间内容的循环
格式:foreach (数组的类型 自定义的变量名 in 需要循环的数组名){执行内容}
多维数组(数组是可以多维的):
表示方式:int num[4][2],表示为4行2列。其遵循的是索引的方式,从0开始。
格式:类型[,1个逗号表示2维 ,2个逗号表示3维] 数组名={ {第一行内容内容中间用,表示每一个逗号表示1列 } , { 第2行内容 } };{ {},{} }有几个{}表示为有几行
例:int[ , ] a={ { aa , bb , cc } , { 11 , 22 , 33 } }; 表示为2行3列。
交错数组:
数组之内在包含数组的结构,叫做交错数组。
格式:交错数组的类型[ ][ ] 数组名={new交错数组的类型[ ]{ 内容 },new交错数组的类型[ ]{ 内容 } };
注意:( new string[ ]{ 内容,内容代表几列 } )的内容代表一个数组。在这个string[ ] [ ]里包含了2个数组。
例:string[][] students = { new string [] { " aa " , " bb " }, new string[] { "90" , "100" } };
交错数组的循环:
foreach (string[] i in students)
{ foreach (string j in i )
Console.WriteLine( j );}
注:把2个new string[]先在交错数组里循环。因为2个new string也是数组,所以里面的内容也要循环才能完成循环显示。
数组是引用类型的*所有引用类型都要用new来建立对象*
数组的3种拷贝方式:
①
Int [] f ={ 1, 2, 3, 4 };
int[] b = new int[f.Length];
for (int i = 0; i < f.Length; i++)
{
b[i] = f[i];
b[0] = 10;
}
Console.WriteLine(a[0]);
Console.WriteLine(b[0]);
②
int[] a ={ 1, 2, 3, 4 };
int[] c = (int[])a.Clone();
.Clone()表示对a进行复制,因为.Clone()是object类型,所以需要强转(int[])
a.CopyTo(b,0);
表示把a拷贝给(c(自定义的数组名),代表从第几位开始拷贝0代表是第一位开始拷贝)
③
int[] c=Array.Copy(a, b, a.Length);
表示把a复制给c,范围是a里的所有元素。
Array.Sort方法:让排序倒过来。
格式:Array.Reverse(数组名);
Array.Sort方法:自动排序。
格式:Array.Sort(数组名);
例:int[] a ={ 9, 8, 3, 4 };
foreach (int b in a)
{Console.WriteLine()}
Array.Sort(a);
Array.Reverse(a);
Split(分割数组)方法的使用:
功能:把一个变量内容先定义成数组,并分割成许多份来分别显示。
格式:需要分割变量的类型 [] 变量名 = 需要分割的变量名 . split(用什么内容来进行分割需要是char类型的必须使用 ‘ ’ );
显示格式:分割变量的类型 自定义变量名 = 变量名[ 0 ]; 表示分割的第一个内容;
分割变量的类型 自定义变量名 = 变量名[ 1 ]; 表示分割的第二个内容;
使用parmas(关键字)参数数组的注意事项:
表示方式: int[] aa ={ 6, 4, 9, 2 };
加了params就可以不用在这里声明数组的值,以上的代码可以省略。
int result = min(aa);
加了params后就可以变成int result=min(6,4,9,2)
static int min(params int[] c)
加params关键字的使用
{ int current = c[0];
for (int i = 1; i < c.Length; i++)
{if (current > c[i])
{current = c[i];}
}
return current;
注: params后只能是一维数组,参数数组只能是最后一个参数
params不能与ref,out一起使用;params不能作为重载的依据。
继承:
继承是一种关系,反映了对象与对象之间的联系,一个对象自动获得另一个对象的部分或全部东西(属性,能力)。加了static关键字的静态类是无法继承的
通过继承可以实现:1,更好的可重用特性。 2,软件更易扩展和更可维护性。
继承的语法:
格式:class 类名(子类也叫派生类): 需要继承的类名(基类)
一个基类可以用多个子类。一个子类不能有多个基类。
例子:一个父亲可以有多个儿子,但一个儿子只能有一个父亲,但儿子可以有多个干爹(接口)。
构造函数的继承:
base关键字:在子类的成员用base可以调用基类的成员。
格式:类名(参数):base(基类的参数){} 例:public son(string a):base(a){}
注:参数的名称必须相同。
继承中的new关键字
功能:如果基类和子类中有2个同样的名字的方法,可以用new关键字来隐藏基类的同名的方法。实现使用子类里自己的方法。
格式:public void fun(){} 调用基类的方法名;
public new void fun( ){} 子类的方法名;
注:如果在子类里使用了new关键字,那就无法再去调用同名的基类的方法。
virtual (关键字)(多态)虚方法的使用:
功能:实现基类调用子类的方法。
只有在基类才能使用(可以没有overiide),如果在基类里有virtual,但在子类里没有override则表示基类方法可以被调用覆盖,但现在不需要覆盖,如果需要可以在子类里添加override。
格式:public virtual void fun(){}
override (关键字)(覆盖)和override配合使用:
只有在子类才能使用,出现override必须要有virtual.
格式:public override void fun(){}
注:virtual和override两个方法名称完全相同。
virtual和override两个方法具有相同的访问限制。
virtual用在基类的方法里,override用在子类的方法里。
多态:
一个倾向于被重写(override)的方法称为虚(virtual)的方法。
对于虚方法,运行时基于对象的类型动态决定来调用同一个方法的不同版本。称为多态。
protected访问修饰符(亲缘关系):
功能:在基类里定义的内容,只有有亲缘关系子类里才能访问。其他类是无法访问。
如果有被重写的内容(带virtual和override)将无法使用protected访问修饰符。
注:在系统定义的program类里操作,也无法把需要使用的内容定义为protected,因为系
统定义的program类是无法和自定义的类有亲缘关系的。
抽象类:
格式:abstract class 类名
特性:抽象类不能实例化。(不能创建对象 即无法使用new命令指定对象)
抽象类可以包含抽象方法,也可以包含其他方法。
不能用sealed修饰符修改抽象类,这意味这抽象类不能被继承。(不能为子类)
从抽象类派生的非抽象类必须包括继承的所有抽象方法的实现。(只能为基类)
抽象类的构造函数:
格式:public 类名(){}
构造函数名必须和抽象类名相同
例: B a = new B();
不能实例化抽象类,所以只能实例化子类。用子类去调用抽象类的方法。
string aa = " ";
string e = a..bb(aa); 或省略string aa= ” ”; 直接string e = a.bb(“aa”);
因为参数aa是string类型,所以在执行方法参数也要是string类型。方法执行时bb.(aa)
里的aa参数必须是实参,必须要赋值。
public abstract class A
{public static string a;
可以使用静态关键字生成变量,但子类是无法调用的。
public A()
{ }
抽象类的构造函数
public abstract string bb(string aa);}
抽象方法
public class B : A
{public override string bb(string aa)
{ return "";}
抽象方法:
特征:抽象方法是隐式的虚方法。
只允许在抽象类中使用抽象方法声明。
抽象方法声明不提供实际的实现,所以没有方法体。
方法声明只是以一个分号结束,并且在签名后没有大括号{}(没有方法体)。
实现由一个重写方法override提供,此重写方法是非抽象的一个成员。
在抽象方法声明中使用static或virtual修饰是错误的。
格式: public abstract 方法类型 方法名( 参数 ); 没有{}。
在子类里 public override 方法类型 方法名(参数){执行代码}
注:抽象方法声明是无法执行方法体,所以方法体只能在抽象类的子类里去执行。
接口:
功能:定义结构让其他类调用并继承的。用来实现多继承。
特征:C#中的多继承的实现方式
接口是纯抽象类,不能包含非抽象方法。
不能采用结成的方法解决,需要有新的技术,这个技术就是接口。
格式:interface 接口名字( 建议名字第一个字母为I ){}
注:接口中不能定义字段,静态的也不可以。
接口中不能定义构造函数。
接口中不能提供访问修饰符,所有方法默认的是public的。
接口中不能定义嵌套类型(enums, structs ,classes, interfaces, or delegates)
接口中不能从一个类或结构继承。
接口的累加(接口继承接口):
例: mobile aa = new mobile();
lt cc = aa;
cc.information();
省略的public 就只能到接口去找才能调用。
aa.information1();
因为有了public,所以可以直接在子类里调用方法。
Console.ReadLine();
interface lt
{ void information();}
interface yd:lt
{void information1();}
此时yd的接口里已经有了2个抽象方法了。因为yd继承了lt的方法,自己又有了一个方法。
class mobile : yd
{void lt.information()
如果使用显示接口,就可以省略public,如果没有使用显示接口,就必须用public
{Console.WriteLine("联通");}
public void information1()
{Console.WriteLine("移动");}}
显示的是“移动”的。
接口的实现(类继承接口):
方法的名称及返回类型必须一致。
所有的参数必须一致。
方法名称前加上接口名称,即采用显示接口实现。
如果采用显示接口实现,方法不能有访问修饰符。所有的接口实现方法都是public。
显示接口:
功能:用来分辨1个或多个接口内定义的相同方法名在同一个子类里执行。
格式: 在方法里用 接口的类名 . 方法名( );
显示执行:接口名 自定义变量名 = 创建过的对象的名;
注意:接口是基类,所以只能用 基类 = 子类。
使用显示接口后实例化的格式:
子类的类名 自定义类名 = new 子类类名();
接口名 自定义接口名 = 自定义的子类类名;
自定义接口名 . 方法名;
多个接口继承:
特征:一个类只可以有一个基类,但可以用无限制的接口。
类必须实现它所继承的接口的全部方法。
接口不能被类继承,但可以继承其他的接口。
密封类:
功能:继承到此为止,无法再被继承。
特征:可以组织一个类成为基类。(结构为密封类)
格式: sealed class 类名{}
注意:结构默认为sealed,任何情况下不能从结构继承。
密封方法:
功能:针对虚方法到此为止,无法再被重写。密封方法(sealed方法)是这个方法的最后一次实现
格式:public sealed override void 方法名( ){}
注意:密封方法不一定需要放在密封类内里。
垃圾回收器:
对象的铲除和归还内存给堆的过程叫做垃圾回收。
对象的创建由构造函数来创建。
对象的铲除由析构函数来铲除。当对象消亡的时候,析构函数被自动执行。
析构函数:
功能:对象的铲除由析构函数来铲除。
格式:~ 类名(){}
特征:析构函数不能有参数,不能任何修饰符而且不能被调用。
注意:不能在结构中声明析构函数。
强制启动垃圾回收器的方法:system.GC.collect();
当垃圾回收器开始工作,你的程序的其他线程都会停下来。尽量避免使用析构函数。
using 语句
功能:提供了一个干净的装置,来控制资源的生命周期。你创建一个对象,这个对象在using程序块结束时将被删除。
格式:using( 需要清理的内容 ){ }
在using语句中声明的变量的类型必须是实现了IDisposable接口。
IDisposable 是系统定义好的一个接口,可以直接选择继承。
Dispose方法是IDisposable接口下的系统定义的一个方法,继承后可以直接调用。
优点:不会干扰程序代码的逻辑。
从问题中抽象出来,并且避免重复。
非常强壮。
从析构函数中调用释放方法的步骤:
类继承IDisposable接口
析构函数调用Dispose方法。
Dispose方法是public,可以在任何事件调用。
Dispose可以安全的调用多此,变量dsposed标记这个方法是否别调用过,稀有资源只在这个方法第一次调用时释放。
Dispose method 调用静态方法GC.SuppressFinalize.这个方法告诉垃圾回收器不要再调用这个对象的析构函数。
这个其他方法都要检查这个对象是否已经释放过了,是的话产生一个异常。
属性:
功能:用来封装字段。属性是有2个访问器组成的。set和get
格式:public 需要封装字段的类型 属性名{ set {需要封装的字段名=value;} get{ return 需要封装的字段名} }
定义被封装私有字段的使用权限:
set是定义可以在外部用来修改封装的内容(value表示从外部传来的内容先保存在这个容器内)
get是定义可以在外部用来显示封装的内容。
属性的访问修饰符只能是public
属性跨越了字段和方法的界限
属性看起来像字段,不过编译器会自动将类似字段的语法格式翻译为类似方法的访问。属性是没有参数的。
属性分3类:
只读属性:
出现get{}命令行为只读属性。
只写属性:
出现set{}命令行为只写属性。
读写属性:
当set{}和get{}命令行都出现为读写属性。
使用属性的限制:
不能通过set访问器初始化类或结构的属性
属性不能作为ref或out参数
一个属性只能有一个get或set访问器。
get或set访问器不能有参数。
不能使用const声明属性。
属性在接口内的声明:
格式:封装字段的类型 属性名{set ; get ;}
因为在接口内不需要加访问修饰符,所以可以不用加public
属性的虚方法:
格式:public virtual 封装字段的类型 属性名字{set{} get{}}
public override 封装字段的类型 属性名字{set{} get{}}
索引器:
格式:public 数据类型 this[数组数量类型目前基本都是int 自定义的参数名]{get {return 需要封装的数组名[自定义的参数名] } set { 需要封装的数组名[自定义参数名] } }
使用索引器封装逻辑上像数组的声明。
使用索引器的get访问器来控制堆索引器的读访问。
使用索引器的set访问器来控制堆索引器的写访问。
在接口中声明索引器:
在结构或类中实现接口的定义的索引器。
索引器非常类似于属性,但索引器可以参数列表,且只能作用在实例对象上,而不能在类上直接作用。
格式:数据类型 this[ 数组数量类型目前基本都是int 自定义参数名] { set;get;}
注:一个类里只能用一个索引器封装一个数组。不能再有另一个同类型的索引器
索引器的重载(Hashtable的使用):
功能:实现在同一类下使用索引器为2个数组进行封装。
格式: Using System.Collections;
使用前必须定义别名
Hashitable 自定义对象名 = new Hashitable ( );
需要建立Hashtable的对象
public 表示value值的数组类型 this[表示key值的数组类型 自定义变量名]
{set { 自定义对象名[ 自定义变量名 ]=value;}
get { return = 自定义对象名 [ 自定义变量名 ];} }
执行时:在Main函数下还要对索引器所在的类创建对象
所在类的类名 自定义对象名 = new 所在类的类名;
自定义对象名 [ 第一个数组的内容类型必须和key类型相同 ] = 第二个数组内容必须和value的类型相同
注意:只能用key的值来定义value的值。不能用value的值得来定义key的值。
索引器的虚方法:
格式:public virtual 所在类数组类型 this[数组数量类型基本都是int 自定义的参数名]
{ set {所在类数组名[自定义的参数名=value ;]
get {return所在类数组名[自定义的参数名];} }
(基类)
public override 所在类数组类型 this[数组数量类型基本都是int 自定义的参数名]
{ set {所在类数组名[自定义的参数名=value ;]
get {return所在类数组名[自定义的参数名];} }
(子类)
委托:
定义:类型是引用类型,是一种安全的封装方法的类型,委托包含对方法的引用,一旦为委托非配了方法,委托将与该方法具有完全相同的行为。
委托属于类,不属于对象,所以执行委托时只能用类名 . 委托名
一个委托封装多个方法,叫做多点传送委托(无法返回类型使用)。
一个委托封装一个方法,叫做简单委托(返回类型的方法使用)。
多点传送委托:
格式: public delegate 被封装方法的返回类型 自定义委托名(参数类型,自定义被封装方法的参数列表名《可以省略》);
执行格式:
先需要创建委托所在类的对象:
所在类的类名 自定义对象名 = new 所在类的类名
如果方法在不同类的里,需要封装的方法的类都需要创建对象
委托所在类的类名.自定义委托名 自定义委托对象名 = new委托所在类的类名 . 自定义委托名(自定义对象名 . 创建对象类里需要封装的方法名《不加方法的小括号》);
实现多个方法累加执行的委托格式:
自定义委托名+ = new 委托所在类的类名 . 自定义委托名(自定义对象名 . 创建对象类里需要封装的方法名《不加方法的小括号》)
如果不需要封装此类的方法则用:
自定义委托名- = new 委托所在类的类名 . 自定义委托名(自定义对象名 . 创建对象类里需要封装的方法名《不加方法的小括号》)
完成显示:自定义委托名();
简单委托:
格式: public delegate 被封装方法的返回类型 自定义委托名(参数类型 自定义被封装方法的参数名);
简单委托必须定义一个数组才能执行
格式: 自定义委托名[ ] 自定义数组名 ={new 自定义委托名(自定义对象名 . 需要封装的方法名), 《需要封装几个方法就要建立几个new》);
需要用for循环执行显示,把需要封装方法用new表示在数组内,每个方法在数组内都是从索引0开始排列,要显示它们只能用:数组名[ i ] 的方式来表达,所以要实现显示必须需要用for循环命令来执行。
执行格式:for(i = 0;i < 数组名. Length; i ++){ 执行代码 }
委托的匿名方法:
功能:实现封装一个和其他方法类型不同的方法;
格式:自定义的委托名+= delegate { 所在类自定义对象名 . 方法名(参数);}
特点:任何参数需要在delegate关键字后的括号中。无法使用 -=的方法取消执行,定义了就无法取消。
事件:
定义:事件是类在发生其关注的事情时用来提供通知的一种方式,是一种监听的机制。
使用事件,对象可以将关于事件或已发生变化的信息通知其他对象。
事件使用委托来触发时将调用的方法提供类型安全的封装。
发布方:把事件信息通知其他对象的对象。
订户:注册到事件的对象。
注意:事件是基于委托来实现的。
发布方格式:先要有方法,然后还要建立委托。
public event 自定义的委托名 自定义的事件名《不要加小括号》;
因为事件只能在本类里使用,所以还需要在事件所在类定义一个触发方法(模拟一个触发的事件)。
public 方法类型 方法名( )
{ if 事件名 != null ) (功能是用来判断有没有执行订购:事件名的+=)
事件名( ) ; }
订购方格式:先创建所在类的对象
(订购) 自定义对象名 . 事件名 += new 所在类名 . 委托名(自定义对象名 . 所需要封装的方法);
方法名( );
然后才能用(触发事件的方法名)调用
事件只执行当前的操作,再多次的同时操作,事件只会执行最后次操作。所以必须分开2次显示
如果事件定义在一个类里,这个类里没有定义过方法,需要调用另一个类里的方法时,需要在没有方法的类里建立需要调用的类的构造函数。在Main函数下需要建立这个2个的对象,使事件所在类的对象和有方法的那个类的对象相同,目的是为了能够让没有方法的那个类调用另一个类里的方法。
例:
在teacher类下建立构造函数:
student b;
public teacher (student d)
{ b = d ;}
public void fun3( )
{ b.fun += new funw( b.fun1);}
事件所在类为student ,在Main函数下:
student a = new student( );
teacher b = new teacher( a );
b.fun3( );
teacher(a)内参数表示student 这个类里的对象a ,使teacher b 和对象a相同
注意:事件只能定义在类里,不能定义在类外。代码里可以有多个事件,多个委托,多个方法。
运算符的重载:
限制:
不能修改现、有操作符的有限级及联合性;
不能修改操作符的多样性:一元,二元
不能发明新的操作符
当应用在基本类型上时不能修改操作符号的含义
有些操作符号不能重载
格式: public static 返回类型 operator 需要执行的操作符号(参数类型 自定义名1,参数类型 自定义名2)
{ 需要操作的字段类型 自定义变量名 = 自定义类名1 . 需要使用的字段名 需要执行的操作符号 自定义类名2 . 需要使用的字段名;
类名或结构名 对象名 = new 类名或结构名(自定义变量名)
自定义的变量是在类里的,必须创建一个对象才能进行调用
return 对象名; }
简便表达式: { return new 返回类型(自定义类名1 . 需要使用的字段名 需要执行的操作符号 自定义类名2 . 需要使用的字段名);}
显示执行: 建立2个需要运算的对象,然后建立需要执行操作符的运算。
例:
hour h1 =new hour(2);
hour h2 =new hour(1);
hour h = h1 - h2 ;
Console.WriteLine( h . h );
h1变量名表示一个结构,在h1结构里有字段hvalue, 在h2结构里也有字段hvalue,把他们2个相 - 就得到h。
h变量名是一个结构,如果需要调用,就需要去h结构里去调用需要封装那个变量的属性,表达式: h . 封装的属性名。
struct hour
{ private int hvalue;
public hour( int v)
{hvalue = v ; } }
public int h
{ get { return hvalue ;} }
均衡操作符:
运算操作符执行不用的2个类型的操作。
例:hour h = a – h1 ;
public static students operator -(int a , students s)
{int b = a – s . grade;
students c = new students( b );
return c ; }
++操作符:
格式: public static 当前类或当前类的派生类的类型 operator ++( 参数类型 自定义名);
{return new 参数类型(自定义参数名 . 当前类需要执行的字段名++) ;}
定义成对操作符号(bool类型的操作符):
成对必须定义2个操作符方法:
bool判断符:= =和! = <和> <=和>=
格式:public static bool operator bool判断符 (参数类型 自定义名)
如果定义了= =
{ return 自定义名 . 字段名 bool判断符 自定义名 . 字段名}
public static bool operator bool判断符 ( 参数类型 自定义名)
就必须在定义个!=
{ return 自定义名 . 字段名 bool判断符 自定义名 . 字段名}
转换操作符:
功能:通过转换的方法来为不同的类型(包括类和结构)进行赋值。
implicit(隐式转换): 如果无论对象中的数据是什么,转换都是安全的,没有数据损失或异常抛出,就是用implicit
一但定义了implicit转换时可以使用隐式或显式两种类型。
explicit(显式转换): 如果对象中的数据在某个范围中时,转换是不安全的:有数据损失或异常抛出,就用explicit
格式1: public static implicit operator 转换输出的类型 ( 需要转换的类型 自定义名)
{ return 需要输出的内容;}
需要输出的类型必须和输出的类型相同
格式2: public static explicit operator 转换输出的类型( 需要转换的类型 自定义类型名)
{ return 需要输出的内容;}
需要输出的类型必须和输出的类型相同
典型的转化例子:
转化为类结构对象的输出:
{转换目标的类名 对象名 = new 转换目标的类名(需要转换的变量名)
return 对象名;}
例: public static implicit operator student《类名》(int a)
{ student b = new student( a ); return b;}
使用了explicit 转换类型,在执行的时候需要再用强制转换命令转换为需要转换的类型。
类与类间的转换:
有继承关系的基类和派生类是不可以相互转化的,有继承关系的基类下的2个派生类是可以进行转换。
注意:
所有的操作符都是public
所有的操作符都是static,操作符不支持多态,不能有virtual,abstract,override,或者sealed限定。
二元操作符有两个参数,一元操作符有一个参数
至少有一个参数是当前类型
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1、大小写区别
2、在C#中的布尔类型为bool,而JAVA为boolean
3、C#有一个不安全模式,在此模式之下可以使用指针
4、有枚举类型
5、代理和索引器
6、运算符重载
7、没有throws关键字
下面开始C#之行。
在开始学习C#之前,先了解下C#语句的特点:
1. C#是区别大小。2. 每一句都以分号结束,不象VB.NET。3. 多个语句通过分号可以写在一行,不过不推荐,因为不清晰。OK,开始了。
先了解下其数据类型:
bool true或false
byte 8位无符号整数
short 16位整数
int 32位整数
long 64位整数
float 32位浮点数
double 64位浮点数
char 16位字符
string 多个16位字符
宽度窄的(即字节数少的)数据类型可以直接赋给较宽的数据类型,并会自动转换为新类型。例:
float a = 9.9f;
int b=4;
a = b;
//上述把一个整型的4转换成了浮点型.同样也可以通过强制类型转换将宽类型的缩成窄类型例: float a = 9.9f;
int b=4;
b = (int)a;
//注意必须把要转换的类型名称放在圆括号内,并放在其前面字符串与数值互换: string a = Convert.ToString(b);
float a = Convert.ToSingle(b);
同样也可以像C语言那样格式化输出:
float a=3.1415926728f;
string b=a.ToString("##.##");
变量与常量声明:
C#中允许一条语句声明同一类型的多个变量
int a,b;
但为了语句清晰推荐将多个声明写成多个语句。
有一点要注意,就是如果在声明数值型变量时没有小数部分,则自动为整数类型,有小数部分的,则自动为double类型,而不是float类型,可通过下面声明,转换为不同类型:
float a=1.2f ; long b=23L ;
对于常量声明,习惯用大写符号来表示常数,如:
const float PI = 3.1415926 ;
对于字符声明,得用单引号括起来,如:
char a = ''d'' ;
还可以这样赋值:
int a = b = c = 2;
虽然方便,但并不推荐,推荐将其拆成三个语句来写,这样结构也清晰。
(注:C#的变量名长度是任意的,可以由数字和大小写字母混合组成,但第一个必须是字母。
关于C#中的转义字符:
\n ------------------------- 换行
\r ------------------------- 回车
\t ------------------------- 制表符
\b ------------------------- 退格
\f ------------------------- 换页
\0 ------------------------- 空符号
\" ------------------------- 双引号
\'' -------------------------单引号
\\ -------------------------反斜杠
还有一个较特殊的,就是@号,只要语句前加@号,即表示@号后面的包括有转义符的都按不进行转义运算。
--------------------------------------------------------------
还是先看个例子吧,因为自己也有体会,一味地看语句,很无聊 ^_^
using System;
class sample
{
static void Main(string[] args)
{
string hey="希望如我所愿";
Console.WriteLine("c#快速入门,"+hey);
}
}
很头开始分析:using 语句说明程序中要用到C#的代码库,接着是个类名,可以包括有多个类,类中的东西都必须放在大括号中,整个程序以Main函数开始。按F5可以编译执行。好,完成第一个C#程序。再来看烦燥的语法:
运算符:
算术运算符:
+ --------------------- 加
- --------------------- 减
* --------------------- 乘
/ --------------------- 除
% --------------------- 求余(即整除后的余数)
逻辑运算符:
& --------------------- 按位与
| --------------------- 按位或
^ --------------------- 按位异或
~ --------------------- 取反
>>n ------------------- 右移n位
<<n ------------------- 左移n位
递增递减运算符:
++ 或 -- 或 += 或 -= 或 *= 或/=
如i=1;i++;即等i=i+1; 其它为同样的道理,不说。
比较运算符:
> 或 < 或 == 或 != 或 >= 或<= 一看就明白,也不说。
C#的条件判断:
if(a > 0)
{
a = -1;
}
else
{
Console.WriteLine(a);
}
条件必须放在括号里.
两个条件的判断,注意括号和条件中的等号
if((a = = 0) && (b>0))
{
a = -1;
b = -1;
}
else
{
Console.WriteLine(a + b);
}
switch 用于多个可能的值,如果有一个匹配,则执行相应代码,每句之后必须有break语句中断后面语句的执行。
switch(a)
{
case 1:
Console.WriteLine("1");
break;
case 2:
Console.WriteLine("2");
break;
case 3:
Console.WriteLine("3");
break;
default:
Console.WriteLine("default");
}
while 循环:
-------------------------------------------
a=1;
while (a<20)
{
a=+=a;
}
只要a<20这个条件为真,则循环加a,直到a<20
------------------------------------------
do-while 循环:
------------------------------------------
a=1;
do
{
a=+=a;
}
while(a<20);
------------------------------------------
do while循环与while循环类似,区别在于do-while循环至少执行一次a+=a;
for 循环:
-------------------------------------------
int j=1;
for(int i=0;i<100;i++)
{
j++;
Console.WriteLine("i = "+i+"j = "+j);
}