一、变量:
声明变量的语法:
变量类型 变量名; 变量名=值;
变量类型 变量名=值;
在使用变量的时候要注意:
变量一定要先声明,再赋值,最后使用
例子:
变量的特点:
1、不能够被重复的声明
2、可以被重复的赋值
c#中常用的变量类型
int:整数类型,只能够存放整数 负二十多亿 正二十多亿
double:小数类型,既可以存放小数,也可以存放整数 比int的范围大的多 精度在15到16位 精确程度 说白了 小数点后面的位数
string:字符串类型。
char :字符类型 最多能存储一个字符,最少也只能存储一个字符
decimal:金钱类型 精度比double的精度还要高 25-26 100000000000
变量的命名:一定要有意义
命名规则: 1 必须以“字母”或_或@符号开头.--不要以数字开头
2 后面可以跟任意“字母”、数字、下划线. 注意: 1)你起的变量名不要与c#系统中的关键字重复. 2)在c#中,大小写是敏感的. 3)同一个变量名不允许重复定义(先这么认为,不严谨)
什么叫做关键字?凡是你写出来之后 发现它变成蓝色的,都是关键字 关键字就是这个单词 vs已经用了,你就不能再用了
咱们给变量起名字 要符合两个规范
1、Pascal:要求你的变量名的首单词的首字母要大写,其余字母都小写 HighSchool 给方法或者类命名
2、Camal:要求首单词的首字母小写,其余首单词字母大写。 highSchool 给变量起名字
camel:首单词小写
bufTracker
myFloat
someVariable
pascal:每个单词首字母都大写
CreateProcess
QueryInterface
SendMessage
-------------------------------------------------------------
二、赋值运算符和赋值表达式
=:不是等于的意思,它表示把等号右边的值,赋值给等号左边的变量。
由=号连接的表达式 叫做 赋值表达式
注意:每个表达式都可以求解出一个值来,对于赋值表达式,我们就认为,等号左边的变量的值就是整个赋值表达式的值。
+号:
如果加号两边有一边是字符串的话,那么这个加号就不再起到相加的作用,而是连接的作用。
报错:语法出现了问题,程序根本不会运行
异常:语法没有问题,但是在程序运行的过程当中出现了错误。就是咱们俗称的bug
占位符:
先挖个坑 再填个坑
注意:
1)、占位符一定要从0开始 依次递增 不许跳跃。
2)、多填坑不会有结果,少填坑会出异常。
3)、按照挖坑的顺序输出
例子:
Console.WriteLine("第一个{0},第二个{1}",1,2); //输出:第一个1,第二个2
-------------------------------------------------------------
三、c#中的转义符
转义符就是'\'加上一个特殊的字符 ,组成了一个具有特殊意义的字符。
\" 表示为一个"
\b 表示退格 放在字符串的两端 没有效果
\n 表示换行
\t 对其 tab键
\\ 表示为\
@符号
1)、取消\在字符串中的转义作用,使它单纯的表示为\
2)、将字符串原样输出
-------------------------------------------------------------
四、运算符
算术运算符:
+ - * / %
由算术运算符连接的表达式叫做算术表达式
在算术表达式中 参与运算的操作数的类型必须一致,也必须和结果的类型一致。
如果不一致的话,满足下列条件,会自动发生转换。
1)、类型必须相兼容 都是数字
2)、小的转大的
如果是大的变小的话 必须使用强制类型转换
语法:
(待转换的类型)要转换的值; 303.6---303 double ---int
int result=(int)303.6;
发生强制类型转换结果会丢失精度
int类型---》double类型 int类型变量*1.0
保留两位小数 使用占位符的方式输出 在占位符的后面加上:0.00..你想要的位数
对于不兼容的类型间的转换 我们使用 Convert这个转换工厂
使用Convert进行转换必须要满足一个条件:面儿上必须过得去。
不管咱们是向控制台输出的,还是从控制台接受的 都是字符串类型。
1、一切类型都可以转换成字符串类型 ToString() "123abv"
例子:
2.5.ToString()//输出2.5
详细用法:(含参数)
http://www.cnblogs.com/huangting2009/archive/2009/02/09/1386596.html
2、算术运算符 ++ -- + - * / %
++又分为 前加加和后加加 -- 分为 前减减和后减减
不管是前加加还是后加加 ,结果就是变量的值都加了1
不管是前减减还是后减减,结果就是变量的值都减了1
前加加和后加加的区别:
相同点:
不管是前加加还是后加加 ,结果就是变量的值都加了1
不同点:如果是前加加,那么首先给这个变量的值自身加一,然后再参与运算。
如果是后加加,那么首先拿原值参与运算,运算完成后,自身加一。
在一个表达式中,如果既有一元运算符 也有二元运算符 首先计算一元运算符,然后再算二元运算符。
因为 一元运算符的优先级要高于二元运算符。
一元运算符:指的就是只需要一个操作数就能完成的运算 ++ --
二元运算符:指的就是至少需要两个操作数才能完成的运算。
复合赋值运算符
+= int number=10; number+=10; number=number+10;
-= number-=10; number=number-10;
*= number*=10; number=number*10;
/= number/=10; number=number/10;
%= number%=10; number=number%10;
关系运算符:是用来描述两个事物之间的关系
> < >= <= == !=
由关系运算符连接的表达式叫做关系表达式
逻辑运算符:
逻辑与 &&
逻辑或 ||
逻辑非 !
又逻辑运算符连接的表达式叫做逻辑表达式
我们要求逻辑表达式的的两边都要放关系表达式或者bool类型的值
& && | ||
表达式1&&表达式2 如果表达式1为false,则第二个表达式就不再计算了
表达式1||表达式2 如果表达式1为true,则第二个表达式也不再计算了
表达式1&表达式2 两边表达式都要计算
表达式1|表达式2 两边表达式都要计算
& | 这两个逻辑运算符已很少在用,&& || 这两个逻辑运算符用的比较多
-------------------------------------------------------------
五、选择结构语句
顺序结构:从上到下一行一行的执行 代码不会发生跳跃
判断结构: if if -else
选择结构:if else-if switch-case
循环结构:while do-while for
if结构语法:
if(关系表达式或者bool类型的值)
{
代码;
}
执行过程:程序运行到if处,首先判断if后面小括号中的条件,如果条件成立的话,则执行if所带的大括号中的代码。
如果条件不成立的话,则不执行,直接跳过if结构。
特点:有可能一条代码都不会执行。
if-else 语法:
if(关系表达式或者bool类型的值)
{
代码;
}
else
{
代码;
}
执行过程:程序运行到if处,首先判断if后面小括号中的条件是否成立,如果条件成立的话,则执行if所带的大括号中的代码。
执行完成后,跳出if-else结构。
如果if后面小括号中的条件不成立,则执行else中的代码,执行完成后,跳出if-else结构。
特点:最少都会执行一条代码。
if 和if-else的区别:
if用来判断单一的条件,而if-else用来判断两种条件。
if else if的语法
if(关系表达式或bool类型的值)
{
代码;
}
else if(关系表达式或bool类型的值)
{
代码;
}
else if(关系表达式或bool类型的值)
{
代码;
}
else if(关系表达式或bool类型的值)
{
代码;
}
else
{
代码;
}
执行过程:程序首先判断第一个if后面小括号中表达式的值,如果为true的话,则执行该if所带的大括号中的代码,执行完成后,
跳出if else-if结构。
如果该if中的表达式的值为false,也就是不成立,则继续向下判断if中的表达式,只要成立的话,就执行该if所带的大括号中的代码,
执行完成后,跳出if else-if结构,如果所有的if后面的小括号中的表达式都为false,则看该 if else-if结构中有没有else,如果有else的话,则执行else中的代码,如果没有的话,则跳出if else-if结构。什么都不做。
swicth-case:主要针对于多个定值的选择判断
语法:
switch(表达式/变量)
{
case 值1:代码;
break;
case 值2:代码;
break;
case 值3: 代码;
break;
.....
default:代码;
break;
}
执行过程:程序运行到switch处,首先计算小括号内表达式或者变量的值,然后拿这个值依次跟每个case后面
所带的值进行匹配,如果匹配成功,则执行该case中的代码,执行完成后,遇到break,跳出switch-case结构,
如果跟每个case的值都不匹配,就看,当前这个switch-case结构中是否有default,如果有default,则执行default
中的代码,执行完成后,遇到break,跳出当前switch-case结构,如果当前这个switch-case结果中,并没有default,
则什么都不做。
break:跳出switch-case结构。
-------------------------------------------------------------
五、异常捕获
try{} catch{}
使用的语法:哪可能出现异常,你就踹它一脚
执行过程:
如果try中的代码出现了异常,则不会继续向下运行,直接跳到catch中,执行catch中的代码
注意:
try和catch中间不允许写任何的代码。
例子:
1 try 2 { 3 Console.WriteLine("请输入整数数字"); 4 int input = Convert.ToInt32(Console.ReadLine()); 5 Console.WriteLine("你刚刚输入的是{0}",input); 6 } 7 catch 8 { 9 Console.WriteLine("出错了,你输入的不是整数数字"); 10 } 11 Console.ReadKey();
-------------------------------------------------------------
六、变量的作用域
就是你能够访问到这个变量的范围。
变量的作用域是从声明它的那个大括号开始,到第一个大括号结束。
-------------------------------------------------------------
七、循环结构语句
while循环的语法:
while(循环条件)
{
循环体;
}
执行过程:程序运行到while处,首先判断while后面小括号中的循环条件是否成立,如果成立的话,
则执行while所带的大括号中的循环体,如果循环条件不成立,则跳出while循环。
循环体执行完一遍后,再去判断循环条件是否成立,如果成立,则继续执行循环体,如果不成立,则跳出当前循环。
一般来说,每个循环中,总有那么一行代码,能够改变循环条件,使循环条件终有一天不再成立。
如果循环当中,没有没有那么一行代码,能够改变循环条件,也就是说,循环条件永远成立,我们
,管这种循环叫做死循环。
while(true)
{
死循环;
}
break:跳出switch-case结构。
跳出当前while循环。
do while循环
语法:
do
{
循环体;
}while(循环条件);
执行过程:程序从上向下运行,首先执行一遍do中的循环体,执行完一遍后,去判断循环条件是否成立,
如果成立的话,则继续执行do中的循环体,如果条件不成立的话,则不执行循环体。
特点:先执行,再判断
for循环
语法:
for(表达式1;表达式2;表达式3)
{
循环体;
}
表达式1:一般为定义循环次数的初始变量
表达式2:循环条件;
表达式3:改变循环条件的那个条件
执行过程:第一次开始执行的时候,首先执行表达式1,声明了一个循环的初始变量,然后执行表达式2,判断
循环条件是否成立,第一次执行循环的时候,并没有执行表达式3,执行完表达式2之后,开始执行循环体,
执行完循环体之后,开始执行表达式3,然后执行表达式2,判断循环条件是否成立,如果成立的话,则执行循环体,
如果不成立的话,则跳出for循环。
当咱们已经知道循环次数的时候 使用for循环。
如果不知道循环次数,而知道循环条件是一个关系表达式或逻辑表达式的时候,只能使用while或者do-while循环。
break:
一般配合着if来使用,当满足某个条件的时候,才break跳出循环。
只能跳出break当前所在的那个循环,不能跳出所有的循环。
(例如:跳出当前整个for循环,而非当次for循环,如果外面有for循环,则只跳出里面的for循环)
例子:
for(var i=1;i<=10;i++)
{ if(i==6) break;
document.write(i);
}
//输出结果:12345
Continue语句:
立即结束本次循环,判断循环条件,如果成立,则进入下一次循环,否则退出循环
-------------------------------------------------------------
八、关于int.TryParse()方法:
例子:
把用户输入的数字转换成我们想要的数字类型,如何做?
可以用Convert.ToInt32("3");
还可以用int.Parse("3");
另外一个方法:
int num = 0;
int.TryParse("3",out num);
具体使用参见下面:
1 string str = "123abc"; 2 3 4 //int number = Convert.ToInt32(str);//把字符串转换为数字 5 6 7 //int number = int.Parse(str);//跟上一行语句功能一样是把字符串转换为数字 8 9 10 //但是,Convert.ToInt32(str)其实调用的是int.Parse(str)方法, 11 12 13 //所以int.Parse(str)的效率会高一点点 14 15 16 int number = 0; 17 18 19 bool b = int.TryParse(str,out number); 20 21 22 Console.WriteLine(number); 23 24 25 Console.WriteLine("转换结果{0}",b); 26 27 28 Console.ReadKey();
bool b = int.TryParse(str, out number);
执行过程:
尝试着将一个字符串类型的变量转换成int类型,如果转换成功的话,首先返回一个true,则将转换成功后的那个int类型的值
放到out后面的那个int类型的变量中保存,如果转换失败的话,则返回一个false,并且将number赋值为0
-------------------------------------------------------------
九、三元表达式 :语法
表达式1?表达式2:表达式3
执行过程:表达式1一般为关系表达式, 如果表达式1为true,则表达式2的值就是整个三元表达式的值。
如果表达式1的值为false,那么表达式3的值就是整个三元表达式的值。
注意:表达式2和表达式3的结果的类型必须一致,并且也要和整个三元表达式的结果的类型一致。
引申开来,求三数字的最大数:
1 //要求用户输入两个数字并且比较大小 2 Console.WriteLine("请输入第一个数字:"); 3 int numberOne = Convert.ToInt32(Console.ReadLine()); 4 //此处如果ReadLine改为Read,则读取的是Char字符而不是String字符串, 5 //并且用户输入字符的话会转为ASCII码的数字值 6 Console.WriteLine("请输入第二个数字:"); 7 int numberTwo = Convert.ToInt32(Console.ReadLine()); 8 Console.WriteLine("请输入第三个数字:"); 9 int numberThree = Convert.ToInt32(Console.ReadLine()); 10 11 //求三个数字谁最大 12 int max = (numberOne > numberTwo ? numberOne : numberTwo) > numberThree ? (numberOne > numberTwo ? numberOne : numberTwo) : numberThree; 13 Console.WriteLine("这两个数字中必较大的是{0}", max); 14 Console.ReadKey();
-------------------------------------------------------------
十、枚举类型
好处:就是方便咱们来写代码
语法:
[public] enum 枚举名
{
值1,
值2,
值3,
......
}
public:访问修饰符 访问的权限 公开的,公用的,没有访问权限,谁都能访问。
enum:声明枚举的关键字
枚举名:要符合命名规范
枚举类型可以跟int类型互相转换,每个枚举类型都可以用一个int类型来表示
将枚举声明到命名空间的下面,类的外面,表示这个命名空间下,所有的类都可以使用这个枚举。
枚举就是一个变量类型 ,int--double string decimal.
只是枚举声明、赋值、使用的方式跟那些普通的变量类型不一样。
枚举类型默认是跟int类型相互兼容的,所以可以通过强制类型转换的语法互相转换。
当转换一个枚举中没有的值的时候,不会抛异常,而是直接将数字显示出来。
枚举同样也可以跟string类型互相转换,如果将枚举类型转换成string类型,则直接调用ToString().
如果将字符串转换成枚举类型则需要下面这样一行代码:
(要转换的枚举类型)Enum.Parse(typeof(要转换的枚举类型),"要转换的字符串");
如果转换的字符串是数字,则就算枚举中没有,也会不会抛异常。
如果转换的字符串是文本,如果枚举中没有,则会抛出异常。
例子:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /// <summary> 2 /// 声明一个枚举 3 /// </summary> 4 public enum QQState 5 { 6 OnLine = 1, 7 OffLine, 8 Leave, 9 QMe, 10 Busy 11 } 12 13 public enum Sesons 14 { 15 春, 16 夏, 17 秋, 18 冬 19 } 20 static void Main(string[] args) 21 { 22 //int number = 10; 23 //QQState state = QQState.OnLine; 24 //int n = (int)state; 25 //Console.WriteLine(n);//输出:1,如果OnLine等俱不赋值,则从零开始依次递增 26 //Console.ReadKey(); 27 #region 将枚举类型强转为int类型 28 //Console.WriteLine((int)QQState.OnLine);//输出:1 29 //Console.WriteLine((int)QQState.OffLine);//输出:2 30 //Console.WriteLine((int)QQState.Leave);//输出:3 31 //Console.WriteLine((int)QQState.QMe);//输出:4 32 //Console.WriteLine((int)QQState.Busy);//输出:5 33 #endregion 34 #region 将int类型强转为枚举类型 35 //int number = 10; 36 //QQState state = (QQState)number; 37 //Console.WriteLine(state);//输出10,如果number赋值1则显示OnLine,超出枚举内范围则直接显示赋值数值 38 //Console.ReadKey(); 39 #endregion 40 #region 将枚举类型转换为字符串 41 //QQState state = QQState.OnLine; 42 //Console.WriteLine(state.ToString()); 43 //Console.ReadKey(); 44 //int number = 10; 45 //double d = 3.14; 46 #endregion 47 #region 字符串类型也可以转换为枚举类型 48 //string str = "10"; 49 //QQState state = (QQState)Enum.Parse(typeof(QQState), str); 50 //Console.WriteLine(state); 51 //Console.ReadKey(); 52 #endregion 53 #region 枚举练习 54 Console.WriteLine("请选择你的在线状态 1---在线 2--不在线 3--离开 4--Q我吧 5---忙碌"); 55 string input = Console.ReadLine(); 56 switch (input) 57 { 58 case "1": QQState state = (QQState)Enum.Parse(typeof(QQState), input); 59 Console.WriteLine("您选择的在线状态是{0}", state); 60 break; 61 case "2": QQState stateTwo = (QQState)Enum.Parse(typeof(QQState), input); 62 Console.WriteLine("您选择的在线状态是{0}", stateTwo); 63 break; 64 case "3": QQState stateThree = (QQState)Enum.Parse(typeof(QQState), input); 65 Console.WriteLine("您选择的在线状态是{0}", stateThree); 66 break; 67 case "4": QQState stateFour = (QQState)Enum.Parse(typeof(QQState), input); 68 Console.WriteLine("您选择的在线状态是{0}", stateFour); 69 break; 70 case "5": QQState stateFive = (QQState)Enum.Parse(typeof(QQState), input); 71 Console.WriteLine("您选择的在线状态是{0}", stateFive); 72 break; 73 default: Console.WriteLine("请输入正确的数字"); 74 break; 75 } 76 Console.ReadKey(); 77 #endregion
-------------------------------------------------------------
十一、声明常量
声明常量的语法:
const 变量类型 常量名=值;
常量一旦声明了,就不能被改变了。
-------------------------------------------------------------
十二、结构体
可以帮助我们一次性声明多个不同类型的变量。
结构的语法:
[访问修饰符] struct 结构名
{
变量。。。/方法/属性
}
访问修饰符:public
struct:声明结构的关键字
例子:
1 public struct Person 2 3 { 4 5 public string Name; 6 7 public int Age; 8 9 public string Hobby; 10 11 public int Popularity; 12 13 public void SayHi() 14 15 { 16 17 // …. 18 19 } 20 21 }
-------------------------------------------------------------
十三、字段和变量本质的区别:
字段在程序运行的时候 可以存储多个值,而变量,只能存一个值。
-------------------------------------------------------------
十四、数组:
当你需要一次性声明多个相同类型的变量的时候?
数组
声明数组的语法:
变量类型[] 数组名=new 变量类型[数组长度];
数组的长度 如果固定了,那么就不能再改变了
声明数组的四种形式:
int[] nums=new int[10];只声明了数组的长度和类型,并没有给数组赋值
int[] nums={1,2,3,4,5,6,7,8,9,0}; 再声明数组的同时,及确定了数组的类型、长度以及数组中的元素的值
===================================================================================
int[] nums=new int[5]{1,2,3,4,5}; 注意:这个数组的长度是几,那么你元素的个数也得是几
int[] nums=new int[]{1,2,3,4,5};
最后两种不建议使用,容易出错或者繁琐
对错:
int[] nums = new int[3]{5,3,8}//个数和声明数必须一致
int[] nums = new int[5]{5,3,8}//错误
int[] nums = new int[]{5,3,8}//正确,可以省略数组个字
-------------------------------------------------------------
十五、冒泡排序法:
int[] numbers={9,8,7,6,5,4,3,2,1,0}; 0 1 2 3 4 5 6 7 8 9
冒泡排序:将一个数组从大到小或者从小到大进行排序
数组 从大到小:降序排列
从小到大:升序排列
第一趟:8 7 6 5 4 3 2 1 0 9 第一趟比较 比较了9次 i=0 j=9 i numbers.Length-1-0
第二趟:7 6 5 4 3 2 1 0 8 9 第二趟比较 比较了8次 i=1 j=8 i numbers.Length-1-1
第三趟:6 5 4 3 2 1 0 7 8 9 第三趟比较 比较了7次 i=2 j=7 i numbers.Length-1-2
第四趟:5 4 3 2 1 0 6 7 8 9 第四趟比较 比较了6次 i=3 j=6 i numbers.Length-1-3
第五趟:4 3 2 1 0 5 6 7 8 9 第五趟比较 比较了5次 i=4 j=5
第六趟:3 2 1 0 4 5 6 7 8 9 第六趟比较 比较了4次 i=5 j=4
第七趟:2 1 0 3 4 5 6 7 8 9 第七趟比较 比较了3次 i=6 j=3
第八趟:1 0 2 3 4 5 6 7 8 9 第八趟比较 比较了2次 i=7 j=2
第九趟:0 1 2 3 4 5 6 7 8 9 第九趟比较 比较了1次 i=8 j=1
1 //外层循环控制比较的趟数 2 3 for(int i=0;i<numbers.Length-1;i++) 4 5 { 6 7 //两两比较 交换 8 9 for(int j=0;j<numbers.Length-1-i) 10 11 { 12 13 if(numbers[j]>numbers[j+1]) 14 15 { 16 17 int temp=numbers[j]; 18 19 numbers[j]=numbers[j+1]; 20 21 numbers[j+1]=temp; 22 23 } 24 25 } 26 27 }
-------------------------------------------------------------
十六、方法:
1、方法。目的:就是将一坨代码进行重用的一种机制。
语法:
[访问修饰符] static 返回值类型 方法名([参数列表])
{
方法体;//
return 返回值
}
访问修饰符:访问的权限 现阶段 咱们都写成public
static:静态的。现阶段写的方法全都写成静态的。
返回值类型:如果这个方法没有返回值 则写一个void,如果有返回值,则写对应的返回值的类型
方法名:必须要符合Pascal 每个单词的首字母都要大写。
参数列表:完成这个方法,所必须要的条件。如果没有参数的话,小括号也不能省略
方法写完后,还要在Main()方法中调用。
调用方法的语法:
类名.方法名();
注意:如果你写的方法跟Main()方法在同一个类中(Program),那么在调用方法的时候,可以省略类名
直接写方法名。
return:
1、返回要返回的值
2、结束当前方法的运行
方法的功能一定要单一。
当方法要返回多个不同类型的值回来的时候,使用out参数。
使用out参数需要注意:
out参数在方法内必须要为其赋值,在方法外,可以不为其赋值。
out参数侧重于返回多个参数。
ref参数侧重于:将一个值带入一个方法内进行改变,改变完成后,再将这个值带出来。
使用ref参数需要注意:
ref参数在方法外必须为其赋值
1、方法的重载。
所谓方法的重载指的就是方法的名字相同,但是参数不同。
参数不同有两种情况:
1、如果参数的类型相同,那么参数的个数就不能相同。
2、如果参数的个数相同,那么参数的类型就不能相同。
params 的用法:
params 构造函数声明数组 而不知道数组长度 用的
在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace ConsoleApplication7 8 { 9 class Program 10 { 11 public static void UseParams(params int[] list) 12 { 13 for (int i = 0; i < list.Length; i++) 14 { 15 Console.WriteLine(list[i]); 16 } 17 Console.WriteLine(); 18 } 19 public static void UseParams2(params object[] list) 20 { 21 for (int i = 0; i < list.Length; i++) 22 { 23 Console.WriteLine(list[i]); 24 } 25 Console.WriteLine(); 26 } 27 static void Main() 28 { 29 UseParams(1, 2, 3); 30 UseParams2(1, 'a', "test"); 31 // An array of objects can also be passed, as long as 32 // the array type matches the method being called. 33 int[] myarray = new int[3] { 10, 11, 12 }; 34 UseParams(myarray); 35 Console.ReadKey(); 36 } 37 } 38 }
更多方法的用法:http://www.cnblogs.com/yank/archive/2012/09/12/2663793.html
-------------------------------------------------------------
十七、对象:
1、面向对象
面向过程:
不管是面向对象 还是面向过程 都是咱们日常生活中的思考方式
1、c语言(面向过程)
2、c# java (两个都是面向对象)
面向过程:把大象装进冰箱里
1、打开冰箱门
2、把大象放进去
3、关闭冰箱门
面向过程:注重的是过程,强调的是动作。
面向对象:
我去中关村 买电脑
1、先搞清楚我要的配置
2、去买
面向对象:找个对象帮你做事儿
总结:
咱们在日常生活中描述一个对象的时候 ,通过描述这个对象的特征和行为来描述这个对象。
在咱们面向对象的思想中。
这个对象的特征 我们管它叫做属性。
这个对象的行为 我们管它叫做方法。
对象一定是特指:
对象一定是真真正正存在的 看得见的 摸的着的。
-------------------------------------------------------------
十八、类:
我们在描述一些对象的时候发现,这些对象具有共同的属性和方法。
我们将这些具有共同属性共同方法的对象 进行进一步的抽象,提取出了
类这个概念。
类就是一个模子,确定了属于这个类的对象应该具有的属性和方法。
//类里面可以写什么呢?
字段、属性、方法、索引器 (不能在类里调用方法,方法的本体可以写在类里面,如果要调用方法,可以把调用方法写在方法里)
类中的成员 ,需要使用对象去调用(静态的除外)
类 ---》对象?
我们管创建对象的这个过程叫做类的实例化。
类中的成员,如果不写访问修饰符,默认为private
private:私有的,只能在当前类的内部访问,出了这个类,就访问不到了。
this的用法:
1、代表当前这个类的对象
2、显示的调用当前类的构造函数
显示的调用当前类的构造函数的例子:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class Student 2 { 3 string _name; 4 public string Name 5 { 6 get { return _name; } 7 set { _name = value; } 8 } 9 char _gender; 10 public char Gender 11 { 12 get { return _gender; } 13 set { 14 if (value != '男' && value != '女') 15 { 16 _gender = '男'; 17 } 18 else 19 { 20 _gender = value; 21 } 22 } 23 } 24 int _age; 25 26 public int Age 27 { 28 get 29 { 30 31 if (_age < 0 || _age > 100) 32 { 33 return _age = 0; 34 } 35 else 36 { 37 38 return _age; 39 } 40 } 41 set { _age = value; } 42 } 43 44 45 /// <summary> 46 /// 类的构造函数 初始化对象用的 47 /// </summary> 48 /// <param name="name"></param> 49 /// <param name="age"></param> 50 /// <param name="gender"></param> 51 /// <param name="chinese"></param> 52 /// <param name="math"></param> 53 /// <param name="english"></param> 54 public Student(string name, int age, char gender, double chinese, double math, double english) 55 { 56 this.Name = name; 57 this.Age = age; 58 this.Gender = gender; 59 this.Chinese = chinese; 60 this.Math = math; 61 this.English = english; 62 } 63 64 65 public Student(double chinese, double math, double english):this(null,0,'\0',chinese,math,english)// 显示的调用当前类的构造函数 66 { 67 68 } 69 70 public Student(string name, int age, char gender):this(name,age,gender,0,0,0) 71 { 72 73 } 74 75 public Student(string name, int age, char gender, double chinese):this(name,age,gender,chinese,0,0) 76 { 77 78 } 79 80 public Student() 81 { 82 83 } 84 85 86 87 public Student(double chinese) 88 { 89 if (chinese < 0 || chinese > 100) 90 { 91 chinese = 0; 92 } 93 this.Chinese = chinese; 94 } 95 96 double _chinese; 97 98 public double Chinese 99 { 100 get { return _chinese; } 101 set { _chinese = value; } 102 } 103 104 double _math; 105 106 public double Math 107 { 108 get { return _math; } 109 set { _math = value; } 110 } 111 112 double _english; 113 114 public double English 115 { 116 get { return _english; } 117 set { _english = value; } 118 } 119 // 一个打招呼的方法:介绍自己叫XX,今年几岁了。是男同学还是女同学。 120 public void SayHello() 121 { 122 Console.WriteLine("大家好,我叫{0},我几年{1}岁了,我是{2}生", this.Name, this.Age, this.Gender); 123 } 124 125 126 //两个计算自己总分数和平均分的方法。{显示:我叫XX,这次考试总成绩为X分,平均成绩为X分} 127 128 public void GetScore() 129 { 130 Console.WriteLine("我叫{0},我的总成绩为{1},我的平均成绩为{2:0.00}", this.Name, this.Chinese + this.Math + this.English, (this.Chinese + this.Math + this.English) / 3); 131 } 132 133 134 }
属性的作用:属性快捷键(按Ctrl+R,E快捷键)
1、主要是保护字段,对字段的取值和赋值进行限定
属性本质上有两块内容组成,一块叫get,一块叫set,通过反编译会发现,这个get和set本质上都是一个方法。
既有get也有set的属性叫做可读可写属性,表示既可以给这个属性赋值,也可以给这个属性取值。
只有get的属性叫做只读属性,表示只能读取这个属性,而不能给这个属性赋值。
只有set的属性叫做只写属性,表示还能给这个属性赋值,而不能给这个属性取值。
需要记住的三个单词
fields:字段
Methods:方法
Properties:属性
在咱们类中 字段就是女人(不对外) 属性就是男人(对外)
类中的成员,如果不加访问修饰符,默认为private
构造函数:构造函数就是一个特殊的方法而已。
1)、构造函数的方法名跟类名一致
2)、构造函数没有返回值,并且连void也不能有
作用:初始化对象
注意:
在你写号了一个类之后,这个类会有一个默认的无参数的并且咱们看不见的构造函数
当咱们在类中写了一个新的无参数的构造函数之后,那个默认的无参数的构造函数就没了,就被干掉了
new到底做了什么事情?
1、在内存的堆中开辟空间
2、在开辟的空间中创建对象
3、调用这个对象的构造函数
项目之间类的引用
如果在一个项目中,需要引用到其它项目的类,需要以下几个步骤:
1、添加引用
2、引用命名空间
什么是静态 什么是非静态
区别:
1、在非静态类中能不能出现静态成员? 答:可以。
2、非静态成员和静态成员在调用上的一些区别。
答:
静态成员在调用的时候,需要使用类名.静态成员;
非静态成员在调用的时候,需要使用对象名.非静态成员名.
*:对象名不能点出来静态成员。
类名也不能点出来非静态成员。
3、静态类中能不能出现非静态成员?
答:不可以。静态类中不允许出现非静态的成员。
静态类中只能有静态的成员。
静态类不允许创建对象
静态方法中不能使用非静态的字段。而非静态的方法中既可以有静态字段,也可以有非静态字段。
静态和非静态的总结:
静态成员中,绝对不允许出现非静态的成员。并且在调用的时候,不能创建静态类的对象,只能使用类名.静态成员名;
非静态成员中,既可以有静态成员,也可以有非静态成员。在非静态成员中,既可以访问到静态成员,也可以访问到
非静态成员。
非静态类访问非静态成员需要使用对象名.非静态成员名
非静态类访问静态成员需要类名.静态成员名。
什么时候使用静态类,什么时候使用非静态类?
1、当你写的类需要被实例化的时候,只能使用非静态类。
2、我们一般把静态类作为工具类来使用。最常见的静态类就是咱们的Console类
-------------------------------------------------------------
十九、字符串:
1、字符串可以看做是char类型的只读数组,可以通过下标去访问字符串中的某一个元素,但是不能给这个元素赋值。因为她
是只读的。
2、
将字符串转换成char数组 调用 ToCharArray()
将char数组转换成字符串 调用new string(要转换的char数组);
例子:
1 //以下是错误代码 2 //string str = "abcdefg"; 3 ////char ch = str[2]; 4 ////ch = 'd'; 5 //str[2] = 'd'; 6 //Console.WriteLine(str[2]); 7 //Console.ReadKey(); 8 //以上是错误代码,不能给字符串赋值,只能读取 9 10 string str = "abcdefg"; 11 //就要将这个字符串中的c改变成d 12 13 //首先要将这个字符串转换成char类型的数组 14 //字符串可以调用ToCharArray这个方法,将自己转换成char类型的数组 15 char[] chs = str.ToCharArray(); 16 chs[2] = 'd'; 17 //for (int i = 0; i < chs.Length; i++) 18 //{ 19 // Console.WriteLine(chs[i]); 20 //} 21 22 //将字符数组转换成字符串 23 //用这个字符数组调用new string(); 24 str = new string(chs); 25 Console.WriteLine(str); 26 Console.ReadKey();
1、所谓字符串的不可变性,指的就是 字符串一旦声明了,它的值就不能再被改变了,
如果你改变了这个字符串的值,其实就是在堆中又重新开辟了一块空间。老值还在。
2、引用命名空间的快捷键:alt+shift+F10
3、string类型在进行重复的拼接赋值操作的时候,之所以速度慢,效率低,是因为它在内存的堆中不停的开辟空间,
而StringBuilder之所以速度快,效率高,是因为在整个的拼接、赋值操作中,它只是操作的一块内存,并没有再单独的
开辟新空间。
StringBuilder的实现和技巧 :
string的替代解决方案就是StringBuilder的使用..它的使用也很简单System.Text.StringBuilder sb = new System.Text.StringBuilder();这样就初始化了一个StringBuilder ..之后我们可以通过Append()来追加字符串填充到sb中..在你初始化一个StringBuilder 之后,它会自动申请一个默认的StringBuilder 容量(默认值是16),这个容量是由Capacity来控制的.并且允许,我们根据需要来控制Capacity的大小,也可以通过Length来获取或设置StringBuilder 的长度..
先来看Length的用法:
1 System.Text.StringBuilder sb = new System.Text.StringBuilder(); 2 sb.Append( "123456789" );//添加一个字符串 3 sb.Length = 3;//设置容量为3 4 Console.WriteLine( sb.ToString() );//这里输出:123 5 6 sb.Length = 30;//重新设置容量为30 7 Console.WriteLine( sb.ToString() + ",结尾");//这里在原来字符串后面补齐空格,至到Length的为30 8 Console.WriteLine( sb.Length );//这里输出的长度为30
通过上面的代码,我们可以看出如果StringBuilder 中的字符长度小于Length的值,则StringBuilder 将会用空格硬填充StringBuilder ,以满足符合长度的设置..如果StringBuilder 中的字符长度大于Length的值,则StringBuilder 将会截取从第一位开始的Length个字符..而忽略超出的部分..
更多关于StringBuilder方法:http://lixianhuei.cnblogs.com/archive/2005/12/27/305708.html
4、字符串的属性 Length 获得该字符串的长度
5、将一个字符串转换成大写 调用这个字符串的 ToUpper()方法。返回这个字符串的大写形式。
将一个字符串转换成小写,调用这个字符串的ToLower()方法。返回这个字符串的小写形式。
将一个字符串跟另一个字符串比较值是否相等,可以调用字符串的Equals这个方法,在括号中填入StringComparison.OrdinalIgnoreCase)
可以忽略大小写的比较。
6、分割字符串 Split() 将字符串按照指定的字符分割,返回一个字符串类型的数组
注意的地方:
Split(new char[]{'要分割的字符','要分割的字符','要分割的字符'},StringSplitOptions.RemoveEmptyEntries);
StringSplitOptions.RemoveEmptyEntries:移除这个字符串数组中的空项
例子:
1 string strNumber = "1 2 3 4 5 6 7 8 9"; 2 string[] nums = strNumber.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);//去除空格符 3 for (int i = 0; i < nums.Length; i++)//遍历输出nums数组中的所有元素:123456789 4 { 5 Console.Write(nums[i]); 6 } 7 Console.WriteLine(); 8 Console.WriteLine(nums);//输出System.String[] 9 Console.ReadKey();
7、Replace 将一个老字符串 替换成一个新的字符串
Contains 判断一个字符串中 是否包含一个子字符串 如果包含 返回true 否则返回false
例子:
1 //字符串的替换 2 string str = "老字符"; 3 str = str.Replace(str, "新字符"); 4 Console.WriteLine(str); 5 Console.ReadKey(); 6 7 //判断是否包含 8 string str = "今天天气好晴朗处处好风光"; 9 if (str.Contains("天好")) 10 { 11 Console.WriteLine("包含"); 12 } 13 else 14 { 15 Console.WriteLine("不包含"); 16 } 17 Console.ReadKey();
8、SubString()截取字符串
例子:
1 substring() 用法 2 string a="aadsfdjkfgklfdglfd" 3 a.substring(5) //截取从第五位开始到以后的所有字符串 4 a.substring(0,5) //截取从第0到第5 之前含第5的所有字符串 5 6 string str = "老赵买的这个手机肯定是真的,钓丝都说是假的"; 7 str = str.Substring(2, 5); 8 Console.WriteLine(str);//输出:买的这个手 9 Console.ReadKey();
9、StartsWith()以....开始
EndsWith() 以.....结束
例子:
判断字符串的开头是否与指定的字符串相同。
比如:
string s = "aabbcc";
那么s.StartsWith("aabb"),返回true;
而
s.StartsWith("aabc"),返回false;
10、Index Of 查找字符或者字符串在一个字符串中出现的位置 如果返回一个-1,表示当前字符串中找不到该字符或者字符串。
11、Last IndexOf 查找一个字符在字符串中最后一次出现的位置,只要找不到那个字符,就返回一个-1
例子:
IndexOf()
查找字串中指定字符或字串首次出现的位置,返首索引值,如:
str1.IndexOf("字"); //查找“字”在str1中的索引值(位置)
str1.IndexOf("字串");//查找“字串”的第一个字符在str1中的索引值(位置)
str1.IndexOf("字",start,end);//从str1第start+1个字符起,查找end个字符,查找“字”在字符串STR1中的位置[从第一个字符算起]注意:start+end不能大于str1的长度
indexof参数为string,在字符串中寻找参数字符串第一次出现的位置并返回该位置。如string s="0123dfdfdf";int i=s.indexof("df");这时i==4。
indexof() :在字符串中从前向后定位字符和字符串;所有的返回值都是指在字符串的绝对位置,如为空则为- 1
string test="asdfjsdfjgkfasdsfsgfhgjgfjgdddd";
test.indexof(’d’) =2 //从前向后 定位 d 第一次出现的位置
test.indexof(’d’,1) =2 //从前向后 定位 d 从第二个字符开始 第一次出现的位置
test.IndexOf('d', 3) =6 //从前向后 定位 d 从第四个字符开始 第一次出现的位置
test.indexof(’d’,5,2) =6 //从前向后 定位 d 从第5 位开始查,查2位,即 从第5位到第7位;
lastindexof() :在字符串中从后向前定位字符和字符串、用法和 indexof() 完全相同。
12、去掉字符串两端的字符,Trim()是去掉两端的 TrimEnd()是去掉字符串结尾的 TrimStart()是去掉字符串开始的
例子:
1 //trim(); 2 void DelSpace() 3 { 4 string strWithSpace = " this is a string with space "; 5 string strWithoutSpace = strWithSpace.Trim(); 6 Console.WriteLine(strWithoutSpace); 7 Console.ReadKey(); 8 }
上面的程序的作用是将字符串strWithSpace前后的空格去掉,输出"this is a string with space"。
trimStart();
用于删除字符串前面的空格
1 以下是代码片段: 2 void DelSpace() 3 { 4 string strWithSpace = " this is a string with space "; 5 string strWithoutSpace = strWithSpace.TrimStart(); 6 Console.WriteLine(strWithoutSpace); 7 Console.ReadKey(); 8 }
上面的程序的作用是将字符串strWithSpace前面的空格去掉,输入"this is a string with space "
1 //trimEnd(); 2 void DelSpace() 3 { 4 string strWithSpace = " this is a string with space "; 5 string strWithoutSpace = strWithSpace.TrimEnd(); 6 Console.WriteLine(strWithoutSpace); 7 Console.ReadKey(); 8 }
上面的程序输出" this is a string with space"
删除指定的字符
Trim()方法还可以删除指定的字符串
1 char[] trimChars = {" ","e","g"}; 2 string strA = strA.trim(trimChars);
-------------------------------------------------------------
二十、类的继承等:
13、我们把这些具有相同属性和相同方法的类,进行进一步抽象的封装,提取出了 父类 这个概念
父类(基类),子类(派生类)
14、继承:减少代码的冗余 说白了 少写点代码
特性:
1、单根性:一个类只能继承与一个父类 只能有一个爹。
2、传递性:如果爹继承了爷爷,并且孙子继承了爹,那么孙子和爹都能使用到爷爷的东西。 啃老族。
15、子类究竟从父类那里继承过来了什么?
子类从父类那里继承了 属性和方法 子类并没有继承父类的私有字段。
子类并没有继承父类的构造函数,但是子类会默认的调用父类无参数的构造函数,
当你在父类中写了一个新的构造函数之后,默认的无参数的就没了,此时子类就
调不到那个父类中默认的无参数的构造函数了。
解决方法有两个:
1、在父类中,再加一个无参数的
2、在子类中显示的调用父类当中的构造函数 使用关键字 base
例子:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 // Student s = new Student(); 6 7 } 8 } 9 10 11 public class Person 12 { 13 string _name; 14 15 public string Name 16 { 17 get { return _name; } 18 set { _name = value; } 19 } 20 21 22 int _age; 23 24 public int Age 25 { 26 get { return _age; } 27 set { _age = value; } 28 } 29 30 char _gender; 31 32 public char Gender 33 { 34 get { return _gender; } 35 set { _gender = value; } 36 } 37 38 public Person(string name, int age, char gender) 39 { 40 this.Name = name; 41 this.Age = age; 42 this.Gender = gender; 43 } 44 45 public Person() 46 { 47 48 } 49 50 51 public void CHLSS() 52 { 53 Console.WriteLine("作为一个人类,你还要回吃喝拉撒睡"); 54 } 55 } 56 57 public class Student : Person 58 { 59 int _id; 60 61 public int Id 62 { 63 get { return _id; } 64 set { _id = value; } 65 } 66 67 68 69 /// <summary> 70 /// 显示的调用父类的构造函数 71 /// </summary> 72 /// <param name="name"></param> 73 /// <param name="age"></param> 74 /// <param name="gender"></param> 75 /// <param name="id"></param> 76 public Student(string name, int age, char gender, int id) 77 : base(name, age, gender) 78 { 79 80 this.Id = id; 81 } 82 83 84 public void Study() 85 { 86 Console.WriteLine("学生会学习"); 87 } 88 }
1、里氏转换:
如果在某一个地方,需要你传一个父类,那么你也可以传一个子类
如果一个父类中装的是子类对象,那么你可以将这个父类 强制转换为对应的子类
可以用父类变量指向子类对象,不能把子类变量指向父类对象:“变量类型”和“对象类型”不一样,盒子中的面包可以贴“面包”、“面食”、“食品”等。
如果一个父类变量指向的是子类对象,那么可以把子类变量指向这个父类变量,但是需要做类型转换: Person p1=(Person)obj1;
例子:
首先:
public class Dog:Animal //Dog类继承了Animal类
Dog dog=new Dog();
Animal a1=dog; //变量是一个标签,对象是一个实际存在的东西
//=其实就是给实在的东西贴标签的过程
Animal a=new Animal();
Dog d1=a; //这是错误的
Animal a2=new Dog();
Dog d2 = a2; //这是错误的,系统无法识别
Dog d3 = (Dog)a2; //这是正确的,(Dog)告诉系统:放心吧,贴的标签是狗
2、is as
is as 都是类型之间的转换
不同点是:is如果转换成功 则返回一个true 否则返回一个false
as 如果转换成功 则返回对应的对象 否则返回一个null
注意:使用as进行转换,成功了则返回对应的对象,失败了则返回null不会报异常。
使用is进行转换,成功了返回一个true,失败了返回一个false。不报异常。
但是 强制类型转换如果成功了,则返回对应的对象,如果失败了,则报异常。
例如:
父类名 对象A = new 子类名A(参数);
子类名B 对象B = (子类名B)对象A;//赋值失败,强制转换失败,报异常