1.运行第一个HelloWorld文件

在C#中,解决方安为一个包,一个项目对应一个java中的Class。

新版HelloWorld

  1. // See https://aka.ms/new-console-template for more information
  2. Console.WriteLine("Hello, World!");

旧版HelloWorld

  1. using System;
  2. namespace _001_开始
  3. {
  4. class Program
  5. {
  6. static void Main(String [] args)
  7. {
  8. Console.WriteLine("Hello World!");
  9. }
  10. }
  11. }

对比旧版HelloWorld,新版HelloWorld更加简洁易懂。

2.C#命名空间

2.1 句法

  1. namespace <namespace_name>
  2. {
  3. //Write code here
  4. }

2.2 官方说法

In C# namespaces are used to group similar type of classes. Two classes with same name in different namespaces never conflict to each other.

在C#中,名称空间用于对相似类型的类进行分组。 在不同名称空间中具有相同名称的两个类永远不会相互冲突。

In C# namespace can be:

在C#中,命名空间可以是:

  • User defined
    用户自定义
  • Pre defined, that is in-built in .NET class library
    预定义,内置在.NET类库中

Here, we need to use using keyword to access defined namespaces.

在这里,我们需要使用using关键字来访问已定义的名称空间。

如果学习过java,可以理解为不同包下可以有相同的类,虽然命名空间不是包,但是可以理解为包的用法。

2.3 例子

  1. using System;
  2. using System.Collections;
  3. namespace namespace1
  4. {
  5. class ABC
  6. {
  7. public void fun()
  8. {
  9. Console.WriteLine("Inside Namespace1");
  10. }
  11. }
  12. }
  13. namespace namespace2
  14. {
  15. class ABC
  16. {
  17. public void fun()
  18. {
  19. Console.WriteLine("Inside Namespace2");
  20. }
  21. }
  22. }
  23. class Program
  24. {
  25. static void Main()
  26. {
  27. namespace1.ABC OB1 = new namespace1.ABC();
  28. namespace2.ABC OB2 = new namespace2.ABC();
  29. OB1.fun();
  30. OB2.fun();
  31. }
  32. }

输出结果:

  1. Inside Namespace1
  2. Inside Namespace2

命名空间的出现,解决了不同空间需要相同类的情况,类似java中不同包可以拥有不同类。

再举一个计算机系统中的例子=,一个文件夹(目录)中可以包含多个文件夹,每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名。
c#-one-001.jpg

3.注释

3.1 单行注释

  1. //这是行注释

3.2 多行注释

  1. /*
  2. * 这是多行注释。
  3. */

3.3 注释快捷键

注释: 先CTRL+K,然后CTRL+C 取消注释: 先CTRL+K,然后CTRL+U

4.编译过程

编译:把我们写的代码翻译成机器可以识别(阅读)的文件

4.1 一般代码编译过程

高级语言 -> 机器语言(由0和1组成的二进制指令文件)

4.2 C#编译

代码 -> 程序集(后缀为.exe 和 后缀 .dll的文件,且需要在.NET框架下运行)

程序集在运行时会编译成机器指令(JIT及时编译)

5.常量

5.1 定义

1.常量可以当做常规的变量,只是他们的值在定义后不能在被修改。

2.常量是固定值,程序执行期间不会改变。常量可以是任何的基本数据类型,比如整数常量,浮点常量,字符串常量或者字符串常量,还有枚举常量。

5.2 例子

例: 整数常量:24小时,365天

小数/浮点常量:圆周率3.14

字符:‘男’

布尔数值:true,false

空常量:null

以及一些其他进制的数值都是常量

0123(八进制)

0x123(十六进制)

符号常量:符号化的常量,也就是给常量取个名字。

5.3 句法

const 常量类型 常量名=值;

例如:

  1. const int numberTwo = 50;//常量 不能够被重新赋值

6.变量

6.1 定义

一个变量只不过是一个供程序操作的存储区的名字。在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。范围内的值可以存储在内存中,可以对变量进行一系列操作。

例:不同的物品需要用到不同容器(鞋盒,水杯,菜篮子)

6.2 数据类型

C# 中提供的基本的值类型大致可以分为以下几类:

类型 举例
整数类型 sbyte、byte、short、ushort、int、uint、long、ulong 和 char
浮点型 float 和 double
十进制类型 decimal
布尔类型 true 或 false 值,指定的值
空类型 可为空值的数据类型

6.3 句法

定义一个变量的格式:

  1. <data_type> <variable_list>;

在这里,data_type 必须是一个有效的 C# 数据类型,可以是 char、int、float、double 或其他用户自定义的数据类型。variable_list 可以由一个或多个用逗号分隔的标识符名称组成。

一些有效的变量定义如下所示:

  1. int i, j, k;
  2. char c, ch;
  3. float f, salary;
  4. double d;

同时可以进行初始化:

  1. int i = 100;

7.运算符

7.1 定义

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。

7.2 分类

C# 有丰富的内置运算符,分类如下:

运算符分类 包含
算数运算符 加(+
减(-
乘(*
除(/
取模(%
自增(++
自减(--
赋值运算符 赋值(=
加等于(+=
减等于(-=
乘等于(*=
除等于(/=
模等于(%=
关系运算符 大于( >
小于( <
大于等于( >=
小于等于( <=
等于( ==
不等于( !=
逻辑运算符 逻辑与(&&
逻辑或(&#124;&#124;
逻辑非(!
位运算符 按位取反(~
按位与(&
按位或(&#124;
异或(^
右移(>>
左移(<<
无符号右移(>>>
其他运算符 sizeoftypeof 和 三元运算符等

7.3 位运算符补充

  1. 位运算符用来对**二进制位**进行操作,包括按位取反(`~`)、按位与(`&`)、按位或(`|`)、异或(`^`)、右移(`>>`)、左移(`<<`)和无符号右移(`>>>`)。位运算符只能对整数型和字符型数据进行操作。

7.3.1 取反(~)

参加运算的一个数据,按二进制位进行“取反”运算。

  1. 运算规则:~1=0 ~0=1

即:对一个二进制数按位取反,即将0变1,1变0。

7.3.2 按位与(&)

参加运算的两个数据,按二进制位进行“与”运算。

  1. 运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;即:两位同时为“1,结果才为“1,否则为0

例如:3&5 即 0000 0011 & 0000 0101 = 0000 0001 因此,3 & 5的值得1。

7.3.3 按位或(|)

参加运算的两个对象,按二进制位进行“或”运算。

  1. 运算规则:0 | 0=0 0 | 1=1 1 | 0=1 1 | 1=1

即 :参加运算的两个对象只要有一个为1,其值为1。

例如:3 | 5,即 0000 0011 | 0000 0101 = 0000 0111 因此,3 | 5的值得7。

7.3.4 异或(^)

参加运算的两个数据,按二进制位进行“异或”运算。

  1. 运算规则:0^0=0 0^1=1 1^0=1 1^1=0

即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。

7.3.5 左移(<<)

运算规则:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。例如: 12345 << 1,则是将数字12345左移1位:
c#-one-002.jpeg

位移后十进制数值变成:24690,刚好是12345的二倍,所以有些人会用左位移运算符代替乘2的操作,但是这并不代表是真的就是乘以2,很多时候,我们可以这样使用,但是一定要知道,位移运算符很多时候可以代替乘2操作,但是这个并不代表两者是一样的。

思考一下:如果任意一个十进制的数左位移32位,右边补位32个0,十进制岂不是都是0了?当然不是!!! 当int 类型的数据进行左移的时候,当左移的位数大于等于32位的时候,位数会先求余数,然后再进行左移,也就是说,如果真的左移32位 12345 << 32 的时候,会先进行位数求余数,即为 12345<<(32%32) 相当于 12345<< 0 ,所以12345<< 33 的值和12345<<1 是一样的,都是 24690。

7.3.6 右移(>>)

同样,还是以12345这个数值为例,12345右移1位: 12345>>1。
c#-one-003.jpeg

右移后得到的值为 6172 和int 类型的数据12345除以2取整所得的值一样,所以有些时候也会被用来替代除2操作。另外,对于超过32位的位移,和左移运算符一样,会先进行位数求余数。

7.3.7 无符号右移(>>>)

无符号右移运算符和右移运算符是一样的,不过无符号右移运算符在右移的时候是补0的,而右移运算符是补符号位的。以下是-12345二进制表示:
c#-one-004.jpeg

对于源码、反码、补码不熟悉的同学,请自行学习,这里就不再进行补充了讲解了,这里提醒一下,在右移运算符中,右移后补0,是由于正数 12345 符号位为0 ,如果为1,则应补1。
c#-one-005.jpeg

7.3.8 原码、反码和补码说明
  1. 一个数可以分成符号位(01负)+ 真值,原码是我们正常想法写出来的二进制。由于计算机只能做加法,负数用单纯的二进制原码书写会出错,于是大家发明了反码(正数不变,负数符号位不变,真值部分取反);再后来由于+0 -0的争端,于是改进反码,变成补码(正数不变,负数符号位不变,真值部分取反,然后+1)。二进制前面的0都可以省略,所以总结来说:计算机里的负数都是用补码(符号位1,真值部分取反+1)表示的。

7.3.9 位运算符和2的关系
  1. 位运算符和乘2、除2在大多数时候是很相似的,可以进行替代,同时效率也会高的多,但是两者切记不能混淆 ;很多时候有人会把两者的概念混淆,尤其是数据刚好是 2468100等偶数的时候,看起来就更相似了,但是对于奇数,如本文使用的12345 ,右移之后结果为6172 ,这个结果就和数学意义上的除以2不同了,不过对于int 类型的数据,除2 会对结果进行取整,所以结果也是6172 ,这就更有迷惑性了。

8.分支语句

分支语句,能让程序在读取到分支语句时,按照不同情况进行不一样的操作,主要的选择语句有if语句和switch语句两个。

8.1 if语句(条件语句)

8.1.1 例子

例:

  • 有一个游乐场,只有年龄不大于16岁的青少年可以进入,判断输入年龄是否符合条件。
  • 让用户输入一个数,判断是奇数还是偶数,并打印出来。
  • 商场举办送礼活动,年龄在18岁到30岁才可以参与活动,年龄是技术才可以获得奖品。
  • ……

以上例子均有一个共同特点,就是“判断”。需要判断是否满足要求的时候就要用到if语句。

8.1.2 图示

以下为判断结构的一般形式:
C#-One-006.png

8.1.3 句法

第一种:

  1. if(条件){
  2. //满足条件时执行语句1
  3. 语句体1;
  4. }

第二种:

  1. if(条件){
  2. //满足条件时执行语句1
  3. 语句体1;
  4. }
  5. else{
  6. //不满足条件执行语句2
  7. 语句体2;
  8. }

第三种:

  1. if(条件1){
  2. //满足条件1时执行语句1
  3. 语句体1;
  4. }else if(条件2){
  5. //满足条件2时执行语句2
  6. 语句体2;
  7. }else{
  8. //前两者都不满足执行语句3
  9. 语句体3;
  10. }

例:

  1. using System;
  2. namespace _001_开始
  3. {
  4. class Program
  5. {
  6. static void Main(String [] args)
  7. {
  8. int age = Convert.ToInt32(Console.ReadLine());
  9. //if语句
  10. if(age <=16){
  11. //当满足条件的时候会执行
  12. Console.WriteLine("可以执行");
  13. }
  14. else{
  15. //当不满足条件的时候会执行
  16. Console.WriteLine("年龄太大,不可执行");
  17. }
  18. Console.WriteLine("程序结束");
  19. }
  20. }
  21. }

8.2 switch语句

8.2.1 例子
  • 有一台自动售货机,里面一共6个商品。用户可以输入1-6选择要购买的商品:
    • 1、矿泉水
    • 2、红茶
    • 3、绿茶
    • 4、雪碧
    • 5、可口可乐
    • 6、脉动

根据用户选择的数字,显示购买商品。

以上例子具有一个共同点,那就是“选择”。需要用到”选择“的时候就会用到Switch语句。

8.2.2 图示

C#-One-007.jpg

8.2.3 句法
  1. switch(变量) {
  2. case 条件1:
  3. 语句体1; //若符合值1,则执行语句体1
  4. break;
  5. case 条件2:
  6. 语句体2; //若符合值2,则执行语句体2
  7. break;
  8. ...
  9. default:
  10. 条件 n + 1; //若符合值n+1,则执行语句体n+1
  11. break;
  12. }

例:

  1. using System;
  2. namespace DecisionMaking
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. /* 局部变量定义 */
  9. char grade = 'B';
  10. switch (grade)
  11. {
  12. case 'A':
  13. Console.WriteLine("很棒!");
  14. break;
  15. case 'B':
  16. case 'C':
  17. Console.WriteLine("做得好");
  18. break;
  19. case 'D':
  20. Console.WriteLine("您通过了");
  21. break;
  22. case 'F':
  23. Console.WriteLine("最好再试一下");
  24. break;
  25. default:
  26. Console.WriteLine("无效的成绩");
  27. break;
  28. }
  29. Console.WriteLine("您的成绩是 {0}", grade);
  30. Console.ReadLine();
  31. }
  32. }
  33. }

当上面的代码被编译和执行时,它会产生下列结果:

  1. 做得好
  2. 您的成绩是 B

9.循环语句

9.1 while循环

9.1.1 例子
  • 如何不断的输出10个9?
  • 当主角血量大于0的时候,怪物一直攻击主角?

以上例子的共同点是”循环“,他们需要反复做相同的事情,这时候需要用到while循环。

9.1.2 图示

C#-One-008.png

9.1.3 句法
  1. while(判断条件){
  2. 循环语句;
  3. 控制条件语句;
  4. //若没有控制条件变化的语句则会一直满足循环条件陷入死循环
  5. }

例:

  1. int i = 1;
  2. while(i >= 10){
  3. Console.WriteLine(i);
  4. i++;
  5. }//当while不满足条件的时候,就跳出循环,执行后面的代码

9.2 do…while循环

9.2.1 与其他循环的区别

不像 forwhile 循环,它们是在循环头部测试循环条件。do…while 循环是在循环的尾部检查它的条件。

do…while 循环与 while 循环类似,但是 do…while 循环会确保至少执行一次循环。

当首次进入循环不满足条件表达式的时候,do…while会先执行一次循环体,while一次都不执行。其他情况下,do…while和while没有区别。

9.2.2 图示

C#-One-009.jpg

9.2.3 句法
  1. do{
  2. 循环体;
  3. }while(条件表达式);

例:

  1. do{
  2. Console.WriteLine(i);
  3. i++;
  4. }while(i<11);

9.3 for循环

9.3.1 例子
  • 循环输出1-10。
  • 输出20个*,在同一行。
  • 循环计算1-100之间所有偶数

以上例子的共同特征是“循环”,而刚好for循环是我们循环之中最常用也是最常见的。

9.3.2 图示

C#-One-010.png

9.3.3 句法
  1. for(初始化;条件表达式;增量表达式){
  2. 循环体;
  3. }

例:

  1. for(int i=0;i<10;i++){
  2. Console.WriteLine(i);
  3. }
  4. 若要转化为while语句
  5. int i = 0; //对应for循环初始化
  6. while(i<10){ //对应条件表达式
  7. Console.WriteLine(i); //对应循环体
  8. i++; //对应增量表达式
  9. }

9.4 跳转控制语句(break、countinue、goto语句)

9.4.1 break
  1. break语句的使用场合主要是switch语句和循环结构。在循环结构中使用break语句,如果执行了break语句,那么就退出循环,接着执行循环结构下面的第一条语句。如果在多重嵌套循环中使用break语句,当执行break语句的时候,退出的是它所在的循环结构,对外层循环没有任何影响。
  1. int i = 0;
  2. //正常情况会输出1-100
  3. while (i<100){
  4. i++;
  5. Console.WriteLine(i);
  6. //判断,如果i的值达到30跳出循环
  7. if(i==30){
  8. break;
  9. }
  10. }
  11. Console.WriteLine("并没有终止程序,只是跳出循环!");

9.4.2 continue
  1. continue语句用在循环语句中,**用于终止某次循环过程**,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
  1. int i = 0;
  2. while (i<100){
  3. i++;
  4. if(i%10==0){
  5. Console.WriteLine();
  6. //跳出该次循环,继续执行循环
  7. continue;
  8. }
  9. Console.WriteLine(i+"\t");
  10. }

9.4.3 goto
  • goto关键字很早就在程序设计语言中出现,尽管goto仍是java的一个保留字,但并未在语言中得到正式使用,java没有goto,但是在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子。带标签的break和continue。
  • “标签”是指后面跟一个冒号的标识符,例如:label:
  • 对java来说唯一用到标签的地方是在循环语句之前,而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方
  1. //打印101-150之间所有的质数
  2. //质数是指在大于1的自然数中,除了1和它本身没有其他因数的自然数
  3. int cont = 0;
  4. //标签
  5. outer:for(int i =101;i<150;i++){
  6. for(int j=2;j<i/2;j++){
  7. if(i%j==0){
  8. //满足条件跳转到 outer标签处
  9. continue outer;
  10. }
  11. }
  12. Console.WriteLine(i+" ");
  13. }

10.小礼物

推荐一款程序员可以使用的字体叫:JetBrains Mono,是一款等间距字体,可以去官网进行下载,里面也写了较多推荐这款字体的理由,程序员必备!这个是传送门