gitee代码传送门配合代码食用更佳
C# 语言是在 C、C++ 的基础上发展而来的,因此在语法形式上有些类似。
掌握 C# 的基本语法是学好 C# 语言的前提。
C#语言是一种强类型语言,要求每个变量都必须指定数据类型。
任何一个程序都离不开选择语句和循环语句,例如登录一个网站需要输入用户名和密码,如果输入正确,可以进入该网站,否则无法登录,这里使用的就是选择语句。
此外,如果输入用户名和密码的次数超过 3 次就不允许登录,则可以使用循环语句进行判断或者使用跳转语句完成。
①注释符的作用
②C#具有3种注释符
//
/*要注释的内容*/
/// 多用来解释类或方法
变量用来在计算机当中存储数据
存储变量的语法
变量类型 变量名;//声明或者定义某个类型的变量
变量名 = 值;//给这个变量进行赋值
//声明并且给变量赋值的简写形式
变量类型 变量名 = 值;
注:=
在这里并不是表示等于而是表示赋值
int
只能存储整数,不能存储小数double
既能存储整数,也能存储小数,小数点后的位数 15~16位。decimal
用来存储金钱,值后面需要加一个m。string
用来存储多个文本,也可以存储空,字符串类型的值需被 双引号引用。char
用来存储单个字符,最多、最少只能存储一个字符,不能存储空,字符类型的值需被 单引号引用。bool
类型用来描述对或错。 b o o l bool bool类型的值只有true
和false
两个值。如果你要是用变量的话,应该先声明再赋值最后使用。
首先要保证的就是这个变量的名字要有意义。
注意
在满足上面一系列的规则之外同时还要满足这一系列的规范。
给变量起名字的时候要满足两个命名规范
变量的作用域就是你能够使用到这个变量的范围。
变量的作用域一般从声明它的那个括号开始到那个括号所对应的结束的括号结束。
在这个范围内,我们可以访问并使用变量。超出这个范围就访问不到了。
由XX运算符连接的表达式称为XX表达式
如:由算术运算符连接的表达式称为算术表达式。
赋值运算符中最常见的是等号,除了等号以外还有很多赋值运算符,它们通常都是与其他运算符连用起到简化操作的作用。
运算符 | 说明 |
---|---|
= |
x = y ,等号右边的值赋值给等号左边的变量,即把变量 y 的值赋给变量 x |
注意:每个表达式我们都可以求解出一个定义,对于赋值表达式而言,等号左边的变量的值,就是整个赋值表达式的值。
运算符 | 说明 |
---|---|
+= |
x+=y ,等同于 x=x+y |
-= |
x-=y ,等同于 x=x-y |
*= |
x*=y ,等同于 x=x*y |
/= |
x/=y ,等同于 x=x/y |
%= |
x%=y ,等同于 x=x%y |
+
号的作用+
号两边有一边是字符串的时候,+
号就起到连接的作用。运算符 | 说明 |
---|---|
+ |
对两个操作数做加法运算 |
- |
对两个操作数做减法运算 |
* |
对两个操作数做乘法运算 |
/ |
对两个操作数做除法运算 |
% |
对两个操作数做取余运算 |
++ |
x ++ 或 ++ x ,等同于x = x + 1 |
-- |
x -- 或 -- x ,等同于x = x - 1 |
需要注意的是,++
和 --
运算符放在操作数前和操作数后是有区别的,如果放在操作数前,需要先将操作数加 1 或减 1,然后再与其他操作数进行运算;如果放在操作数后,需要先与其他操作数进行运算,然后操作数自身再加 1。
前加加减减示例a = 2,b = ++a + 3
⟶ \longrightarrow ⟶ a += 1, b = 3 + 3
后加加减减示例a = 2,b = a++ + 3
⟶ \longrightarrow ⟶ b = 2 + 3, a += 1
对于像++
、--
这样只需要一个操作数就能够完成运算的符号,我们称为一元运算符。
对于+
、-
、*
、/
、%
这样需要两个或以上才能完成运算的操作符,我们称为二元运算符。
一元运算符的优先级要高于二元运算符。
如果在一个表达式当中,既有一元运算符,又有二元运算符,我们首先计算一元运算符。
关系运算符是用来描述两个事物之间的关系
关系表达式的结果是bool
类型
运算符 | 说明 |
---|---|
== |
表示两边表达式运算的结果相等,注意是两个等号 |
!= |
表示两边表达式运算的结果不相等 |
> |
表示左边表达式的值大于右边表达式的值 |
< |
表示左边表达式的值小于右边表达式的值 |
>= |
表示左边表达式的值大于等于右边表达式的值 |
<= |
表示左边表达式的值小于等于右边表达式的值 |
在使用逻辑运算符时需要注意逻辑运算符两边的表达式以及返回的结果都是布尔类型的
运算符 | 含义 | 说明 |
---|---|---|
&& |
逻辑与 | 如果运算符两边都为 True,则整个表达式为 True,否则为 False;如果左边操作数为 False,则不对右边表达式进行计算,相当于“且”的含义 |
|| |
逻辑或 | 如果运算符两边有一个或两个为 True,整个表达式为 True,否则为 False;如果左边为 True,则不对右边表达式进行计算,相当于“或”的含义 |
! |
逻辑非 | 表示和原来的逻辑相反的逻辑 |
注:逻辑与的优先级要高于逻辑或
if-else
的简化写法
语法
表达式1?表达式2:表达式3;
如果表达式1可以计算出true,那么表达式2的值就是整个三元表达式的值
如果表达式1可以计算出false,那么表达式3的值就是整个三元表达式的值
注意:表达式2的结果类型必须跟表达式3的结果类型一致,并且也要跟整个三元表达式的结果类型一致。
使用方法:先挖个坑,再填个坑;挖坑就是“,”后变量的个数,填坑就是占位符的使用。从0开始依次递增。
使用占位符需要注意的地方
Console.WriteLine("第一个数字是{0},第二个数字是{1},第三个数字是{2}", n1, n2, n3);
转义符指的就是一个’ \ '+ 一个特殊的字符,组成了一个具有特殊意义的字符
转义字符 | 等价字符 |
---|---|
\' |
单引号 |
\" |
双引号 |
\\ |
反斜杠 |
\0 |
空 |
\a |
警告(产生鸣笛音) |
\b |
退格(放在字符串两边没有效果) |
\f |
换页 |
\n |
换行 |
\r |
回车 |
\t |
水平制表符 |
\v |
垂直制表符 |
@
符号\
在字符串中的转义作用,使其单纯的表示为一个\
Console.WriteLine(@"今天天气好清凉
处处好风光");
我们要求等号两边参与运算的操作数的类型必须一致,如果不一致,满足下列条件会发生自动类型转化,或者称之为隐式类型转换。
满足下面两个条件才能发生隐式类型转换
int
和double
兼容(都是数字类型)double > int
满足下面两个条件才能发生显式类型转换
int
和double
兼容int < double
int number = 10;
//int ---> double
//目标类型 = 源类型
double d = number; //自动类型转换 隐式类型转换
double d1 = 303.6;
//double ---> int
//目标类型 = (目标类型)原类型
int n = (int)d1;//强制类型转换,显示类型转换
Console.WriteLine(n); //303
string
和double
、int
不兼容。int
类型,而字符串"abc"看起来就不能转成int
类型。Convert底层就是使用Parse,所以Parse也会抛异常,而TryParse转化失败不会抛异常
int.Parse("123abc");
double.Parse("123abc");
decimal.Parse("123abc");
int.TryParse("123abc");
double.TryParse("123abc");
decimal.TryParse("123abc");
所有类型都能够转换成string类型
//int n = 10;
//double n = 3.14;
//decimal n = 20000m;
QQstate n = QQstate.Busy;
string s = n.ToString();
Console.WriteLine(s);
无论世界上有多少语言、又将出现多少语言,他们的骨架都是这三个结构“顺序结构”、“选择结构”和“控制结构”。
顺序结构:程序从Main函数进入,从上到下一行一行的执行,不会落下任何一行。
选择结构:if、if-else、if-else-if、switch-case
循环结构:while、do-while、for、foreach
语法
if(判断条件)
{
代码块;
}
判断条件:一般为关系表达式或者bool类型的值亦或是bool类型的变量。
执行过程:当判断条件为 True 时执行代码块中的内容,否则不执行并跳出if-else结构。
if
结构的特点:先判断再执行,最多执行一条代码。
作用:用于一种情况的判断
语法
if (判断条件)
{
代码块1;
} else {
代码块2;
}
判断条件:一般为关系表达式或者bool类型的值亦或是bool类型的变量。
执行过程:上面语句的执行过程是当 if 中的布尔表达式的结果为 True 时执行代码块1,否则执行代码块2。代码块1或者2执行完之后,就跳出if-else结构。
if-else
结构的特点:先判断再执行,最少执行一条代码。else
永远只跟离它最近的那个if
配对。
作用:用于两种情况的判断
语法
if (判断条件1)
{
代码块1;
} else if (判断条件2){
代码块2;
}
...
else {
代码块n;
}
判断条件:一般为关系表达式或者bool
类型的值亦或是bool
类型的变量。
执行过程:先判断条件1 的值是否为 True,如果为 True,执行代码块 1,整个语句结束,否则依次判断每个判断条件的值,如果都不为 True,执行else
语句中的语句块 n。
作用:用于处理多种情况的区间判断
需要注意的是,在上面的语法中最后一个 else{} 语句是可以省略的。如果省略了 else{} 语句,那么多分支的 if 语句中如果没有判断语句的值为 True 的语句,则不会执行任何语句块。
语法
switch(变量或者表达式的值)
{
case 值1:要执行的代码;
break;
case 值2:要执行的代码;;
break;
case 值3:要执行的代码;
break;
......
default:要执行的代码;
break;
}
执行过程:程序执行到switch处,首先将括号中变量或者表达式的值计算出来,
然后拿着这个值依次跟每个case后面所带的值进行匹配,一旦匹配成功,则执行该case所带的代码,执行完成后,遇到break,跳出switch-case结构。
如果跟每个case所带的值都不匹配,就看当前这个switch-case结构中是否存在default,如果有default,则执行default中的语句,如果没有default,则该switch-case结构什么都不做。
作用:用来处理多条件的定值判断。只不过switch-case能够处理的,if-else也能够处理
语法
while (循环条件)
{
循环体;
}
执行过程: 程序运行到while处, 首先判断while所带的小括号内的循环条件是否成立,
如果成立的话, 也就是返回一个true, 则执行循环体, 执行完一遍循环体后, 再次回到
循环条件进行判断, 如果依然成立, 则继续执行循环体, 如果不成立, 则跳出while循环。
在while循环当中, 一般总会有那么一行代码, 能够改变循环条件, 使之终有一天不再成立,
如果没有那么一行代码能够改变循环条件, 也就是循环条件永远都成立, 我们称之这种循环叫做死循环。
最简单的最常用的死循环
while (true) {}
特点:先判断,再执行,有可能一遍循环都不执行
语法
do
{
循环体;
}while(循环条件)
执行过程: 程序首先会执行do中的循环体, 执行完成后, 去判断do-while循环的循环条件, 如果成立, 则继续执行do中的循环体, 如果不成立, 则跳出do-while循环。
特点: 先循环, 再判断, 最少执行一遍循环体。
语法
for(表达式 1; 表达式 2; 表达式3)
{
循环体;
}
表达式1一般为声明循环变量,记录循环的次数 (int i=0;)
表达式2一般为循环条件 (i<10)
表达式3一般为改变循环条件的代码,使循环条件终有一天不再成立 (i++)。
执行过程:程序首先执行表达式1,声明了一个循环变量用来记录循环的次数,
然后执行表达式2 , 判断循环条件是否成立,如果表达式 2 返回的结果为true,
则执行循环体:当执行完循环体后,执行表达式3,然后执行表达式 2 继续判断循环条件是否成立,
如果成立则继续执行循环体,如果不成立,则跳出for循环。
switch-case
结构break
一般不单独的使用,而是跟着if判断一起使用,表示当满足某些条件的时候,就不再循环了。
continue
会跳过当前循环中的代码,强制开始下一次循环。
与变量不同的是,常量在第一次被赋值后值就不能再改变。定义常量需要使用关键字 const 来完成。
语法
const 变量语法 变量名 = 值;
需要注意的是,在定义常量时必须为其赋值,因为不赋值的话以后就再也不能赋值了。另外,也可以同时定义多个常量。
在程序中使用常量也会带来很多好处,包括增强了程序的可读性以及便于程序的修改。例如在一个计算率的程序中,为了保证程序中的税率统一,设置一个名为 TAX 的常量来完成,如果需要修改税率只修改该常量的值即可。
枚举就是一种变量类型。只是枚举声明、赋值、使用的方式跟那些普通的变量类型不一样。
枚举的作用:枚举可以规范开发
举个例子说明为什么会有枚举这个东西?
比如说你现在和三个人共同做个某某大学管理系统。这是你们四个人都这些事情,并且都分配了不同的模块,比如存储性别,每个人的定义方法都不相同,你们这个时候我们可以共同定义性别的规范,这是就可以使用枚举规范我们的开发。
语法
//声明以及使用
[public] enum 枚举名
{
值1,
值2,
值3,
......
}
public:访问修饰符。公开的公共的,哪都可以访问。
enum:关键字,声明枚举的关键字
枚举名:要符合Pascal命名规范
将枚举声明到命名空间的下面,类的外面,表示这个命名空间下,所有的类都可以使用这个枚举。
public enum Season
{
春,
夏,
秋,
冬
}
Season s = Season.春;
枚举类型和int类型相互转换
枚举类型默认是跟int类型相互兼容的,所以可以通过强制类型转换的语法互相转换。
当转换一个枚举中没有的值的时候,不会抛异常,而是直接将数字显示出来。
枚举类型和string类型相互转换
枚举同样也可以跟string类型互相转换,如果将枚举类型转换成string类型, 则直接调用ToString()
;
如果将字符串转换成枚举类型则需要下面这样一行代码:
(要转换的枚举类型)Enum.Parse(typeof(要转换的枚举类型), "要转换的字符串");
如果转换的字符串是数字,则就算枚举中没有,也不会抛异常。
如果转换的字符串是文本,如果枚举中没有,则会抛异常。
结构作用:可以帮助我们一次性声明多个不同类型的变量。
[public] struct 结构名
{
成员; //字段
}
变量在程序运行期间只能存储一个值,而字段可以存储多个值。
数组作用:可以帮助我们一次性存储多个相同类型的变量。
通过下标或者索引去访问和赋值数组中的元素。
语法
数组类型[] 数组名 = new 数组类型[数组长度];
数组的长度一旦固定了,就不能够再改变了。
通过下方两个操作可以实现数组的升序和降序。
Array.Sort(数组); //升序
Array.Reverse(数组); //反转数组
方法就是将一堆代码进行重用的一种机制
语法
[public] static 返回值类型 方法名([参数列表])
{
方法体;
}
public:访问修饰符,公开的, 公共的,哪都可以访问
static:静态的
返回值类型:如果不需要写返回值,写void
方法名:Pascal 每一个单词的首字母都大写,其余字母小写
参数列表:完成这个方法所必须要提供给这个方法的条件。如果没有参数,小括号也不能省略。
方法写好后,如果想要被执行,必须要在Main()函数中调用。
方法的调用语法
类名.方法名([参数]);
在某些情况下,类名是可以省略的,如果你写的方法跟Main()函数同在一个类中,这个时候,类名可以省略。
我们在Main()
函数中,调用Test()
函数,我们管Main()
函数称之为调用者,管Test()函数
称之为被调用者。
如果被调用者想要调用者的值:
1.传递参数
2.使用静态字段来模拟全局变量
(CSharp没有全局变量,但是可以用静态字段模拟全局变量,静态变量的作用域是声明的类当中)
如果调用者想要被调用者的值:
1.return 返回值;
方法需要注意的地方
1.不管是实参还是形参,都是在内存中开辟空间。
2.方法的功能一定要单一。错误示范:GetMax(int n1, int n2) //判断闰年
3.方法中最忌讳的就是出现提示用户输入的字眼,所以你需要尽可能地不使用Console.WriteLine()
方法来达到目的。
如果你在一个方法中,返回多个相同类型的值的时候,可以考虑返回一个数组。
但是,如果返回多个不同类型的值的时候,返回数组就不行了,那么这个时候,我们可以考虑使用out参数。
out参数就侧重于在一个方法中返回多个不同类型的值。
out参数要求在方法的内部必须为其赋值。
out意思就是返回多余的值。
能够将一个变量带入一个方法中进行改变,改变完成后,再讲改变后的值带出方法。
ref参数要求在方法外必须为其赋值,而方法内可以不赋值。
将实参列表中跟可变参数数组类型一致的元素都当作数组的元素去处理。
params 参数必须是形参表中最后一个参数。一个形参列表中只能有一个params参数。
方法的重载指的就是方法的名称相同,但是参数不同。
参数不同,分为两种情况
1.如果参数的个数相同,那么参数的类型就不能相同。
2.如果参数的类型相同,那么参数的个数就不能相同。
注:方法的重载跟返回值没有关系
方法自己调用自己
异常是指 语法上没有任何错误,在程序运行的过程当中,由于某些原因出现了问题,使程序不能再正常的运行。
我们在程序中经常会出现各种各样的异常,你如果想要你的程序变得坚强一些。
在你的代码中应该经常性的使用try-catch来进行异常捕获。
哪行代码有可能出现异常,你就try它一脚。
语法
try
{
可能会出现异常的代码块;
}
//try和catch之间不能有其它的代码
catch
{
出现异常后要执行的代码块;
}
执行过程:如果try中的代码没有出现异常,那么catch中的代码不会执行。
如果try中的代码出现了异常,那怕这行出现异常的代码后面还有一百行都不会执行了。
而是直接跳到catch中执行代码。
Random r = new Random();
int rNumber = r.Next(1, 11); //左闭右开