C#完整教程_c#教程
目录
第一部分:C# 基础
控制流
第二部分:面向对象编程(OOP)
第三部分:高级特性
第四部分:文件与 I/O 操作
第五部分:数据库操作
第六部分:图形用户界面(GUI)
第七部分:Web 开发
第八部分:游戏开发
第九部分:测试与调试
第十部分:部署与发布
第一部分:C# 基础
-
C# 简介
- C# 的历史与特点
- .NET 框架与 .NET Core/.NET 5+ 的关系
- 开发环境:Visual Studio、Visual Studio Code、Rider
-
第一个 C# 程序
- Hello World 程序
- 程序结构:命名空间、类、方法
- 编译与运行
-
变量与数据类型
- 基本数据类型:
int
,float
,double
,bool
,char
,string
- 变量声明与初始化
- 常量:
const
- 类型转换:隐式转换与显式转换
- 基本数据类型:
-
- 算术运算符:
+
,-
,*
,/
,%
- 比较运算符:
==
,!=
,>
,<
,>=
,<=
- 逻辑运算符:
&&
,||
,!
- 赋值运算符:
=
,+=
,-=
,*=
,/=
- 三元运算符:
? :
-
- 数组与字符串
-
- 数组:声明、初始化、访问、遍历
- 多维数组与锯齿数组
- 字符串操作:
string
,StringBuilder
句:
break
,continue
,return
- 算术运算符:
运算符
算数运算符
1. 加法运算符(+
)
加法运算符用于将两个数值相加,也能用于拼接字符串。
using System;class Program{ static void Main() { int num1 = 5; int num2 = 3; int sum = num1 + num2; Console.WriteLine($\"两数相加的结果: {sum}\"); string str1 = \"Hello\"; string str2 = \" World\"; string combinedStr = str1 + str2; Console.WriteLine($\"字符串拼接结果: {combinedStr}\"); }}
2. 减法运算符(-
)
减法运算符用于从一个数值中减去另一个数值。
using System;class Program{ static void Main() { int num1 = 5; int num2 = 3; int difference = num1 - num2; Console.WriteLine($\"两数相减的结果: {difference}\"); }}
3. 乘法运算符(*
)
乘法运算符用于将两个数值相乘。
using System;class Program{ static void Main() { int num1 = 5; int num2 = 3; int product = num1 * num2; Console.WriteLine($\"两数相乘的结果: {product}\"); }}
4. 除法运算符(/
)
除法运算符用于将一个数值除以另一个数值。当操作数为整数时,结果会截断小数部分;若有一个操作数为浮点数,结果则为浮点数。
using System;class Program{ static void Main() { int intNum1 = 10; int intNum2 = 3; int intQuotient = intNum1 / intNum2; Console.WriteLine($\"整数相除的结果: {intQuotient}\"); double doubleNum1 = 10.0; double doubleNum2 = 3.0; double doubleQuotient = doubleNum1 / doubleNum2; Console.WriteLine($\"浮点数相除的结果: {doubleQuotient}\"); }}
5. 取模运算符(%
)
取模运算符用于计算两个数值相除后的余数。
using System;class Program{ static void Main() { int num1 = 10; int num2 = 3; int remainder = num1 % num2; Console.WriteLine($\"两数取模的结果: {remainder}\"); }}
6. 自增运算符(++
)
自增运算符用于将变量的值加 1。可分为前缀自增(++variable
)和后缀自增(variable++
)。前缀自增会先将变量的值加 1,再返回变量的值;后缀自增则先返回变量的值,再将变量的值加 1。
using System;class Program{ static void Main() { int num = 5; int prefixIncrement = ++num; Console.WriteLine($\"前缀自增后的结果: {prefixIncrement}\"); num = 5; int postfixIncrement = num++; Console.WriteLine($\"后缀自增后的结果: {postfixIncrement}\"); Console.WriteLine($\"后缀自增后变量的值: {num}\"); }}
7. 自减运算符(--
)
自减运算符用于将变量的值减 1。同样分为前缀自减(--variable
)和后缀自减(variable--
)。前缀自减先将变量的值减 1,再返回变量的值;后缀自减先返回变量的值,再将变量的值减 1。
using System;class Program{ static void Main() { int num = 5; int prefixDecrement = --num; Console.WriteLine($\"前缀自减后的结果: {prefixDecrement}\"); num = 5; int postfixDecrement = num--; Console.WriteLine($\"后缀自减后的结果: {postfixDecrement}\"); Console.WriteLine($\"后缀自减后变量的值: {num}\"); }}
布尔逻辑运算符
在 C# 里,布尔逻辑运算符用于对布尔类型的值进行操作,其运算结果同样是布尔类型(true
或者 false
)。下面为你详细介绍 C# 中常见的布尔逻辑运算符,同时给出相应的代码示例。
1. 逻辑与运算符(&&
)
当两个操作数都为 true
时,逻辑与运算符的运算结果才为 true
;只要有一个操作数为 false
,结果就为 false
。它采用短路求值的方式,也就是说,若第一个操作数为 false
,则不会再计算第二个操作数。
using System;class Program{ static void Main() { bool condition1 = true; bool condition2 = false; bool result = condition1 && condition2; Console.WriteLine($\"逻辑与运算结果: {result}\"); }}
2. 逻辑或运算符(||
)
只要两个操作数中有一个为 true
,逻辑或运算符的运算结果就为 true
;只有当两个操作数都为 false
时,结果才为 false
。它也采用短路求值的方式,若第一个操作数为 true
,则不会再计算第二个操作数。
using System;class Program{ static void Main() { bool condition1 = true; bool condition2 = false; bool result = condition1 || condition2; Console.WriteLine($\"逻辑或运算结果: {result}\"); }}
3. 逻辑非运算符(!
)
逻辑非运算符是一元运算符,它会对操作数的布尔值取反。若操作数为 true
,则结果为 false
;若操作数为 false
,则结果为 true
。
using System;class Program{ static void Main() { bool condition = true; bool result = !condition; Console.WriteLine($\"逻辑非运算结果: {result}\"); }}
4. 逻辑异或运算符(^
)
当两个操作数的布尔值不同时,逻辑异或运算符的运算结果为 true
;若两个操作数的布尔值相同,则结果为 false
。
using System;class Program{ static void Main() { bool condition1 = true; bool condition2 = false; bool result = condition1 ^ condition2; Console.WriteLine($\"逻辑异或运算结果: {result}\"); }}
5. 按位逻辑与运算符(&
)和按位逻辑或运算符(|
)
&
和 |
既可以用作按位运算符处理整数类型,也能当作逻辑运算符处理布尔类型。与 &&
和 ||
不同的是,它们不会进行短路求值,也就是说,无论第一个操作数的结果如何,都会对第二个操作数进行计算。
using System;class Program{ static void Main() { bool condition1 = true; bool condition2 = false; bool andResult = condition1 & condition2; bool orResult = condition1 | condition2; Console.WriteLine($\"按位逻辑与运算结果: {andResult}\"); Console.WriteLine($\"按位逻辑或运算结果: {orResult}\"); }}
位运算符
在 C# 中,位运算符用于对整数类型的操作数按二进制位进行操作。下面为你详细介绍常见的位运算符及其用法,并给出相应的代码示例。
1. 按位与运算符(&
)
按位与运算符会对两个操作数的对应二进制位进行与运算。只有当两个对应位都为 1 时,结果的该位才为 1,否则为 0。
using System;class Program{ static void Main() { int num1 = 5; // 二进制: 0101 int num2 = 3; // 二进制: 0011 int result = num1 & num2; // 二进制: 0001,十进制: 1 Console.WriteLine($\"按位与结果: {result}\"); }}
2. 按位或运算符(|
)
按位或运算符会对两个操作数的对应二进制位进行或运算。只要两个对应位中有一个为 1,结果的该位就为 1,只有当两个对应位都为 0 时,结果的该位才为 0。
using System;class Program{ static void Main() { int num1 = 5; // 二进制: 0101 int num2 = 3; // 二进制: 0011 int result = num1 | num2; // 二进制: 0111,十进制: 7 Console.WriteLine($\"按位或结果: {result}\"); }}
3. 按位异或运算符(^
)
按位异或运算符会对两个操作数的对应二进制位进行异或运算。当两个对应位不同时,结果的该位为 1,相同时为 0。
using System;class Program{ static void Main() { int num1 = 5; // 二进制: 0101 int num2 = 3; // 二进制: 0011 int result = num1 ^ num2; // 二进制: 0110,十进制: 6 Console.WriteLine($\"按位异或结果: {result}\"); }}
4. 按位取反运算符(~
)
按位取反运算符是一元运算符,它会对操作数的每个二进制位进行取反操作,即 0 变为 1,1 变为 0。
using System;class Program{ static void Main() { int num = 5; // 二进制: 0101 int result = ~num; // 二进制补码表示:先取反得到 1010,再考虑符号位等,最终结果为 -6 Console.WriteLine($\"按位取反结果: {result}\"); }}
5. 左移运算符(<<
)
左移运算符会将操作数的二进制位向左移动指定的位数,右边空出的位用 0 填充。左移 n 位相当于将该数乘以 2 的 n 次方。
using System;class Program{ static void Main() { int num = 5; // 二进制: 0101 int result = num << 2; // 二进制: 010100,十进制: 20 Console.WriteLine($\"左移 2 位结果: {result}\"); }}
6. 右移运算符(>>
)
右移运算符会将操作数的二进制位向右移动指定的位数。对于无符号数,左边空出的位用 0 填充;对于有符号数,左边空出的位用符号位填充(正数补 0,负数补 1)。右移 n 位相当于将该数除以 2 的 n 次方(向下取整)。
using System;class Program{ static void Main() { int num = 20; // 二进制: 010100 int result = num >> 2; // 二进制: 000101,十进制: 5 Console.WriteLine($\"右移 2 位结果: {result}\"); }}
关系运算符
using System;class Program{ static void Main() { int a = 10; int b = 20; // 等于 Console.WriteLine($\"a == b: {a == b}\"); // false // 不等于 Console.WriteLine($\"a != b: {a != b}\"); // true // 大于 Console.WriteLine($\"a > b: {a > b}\"); // false // 小于 Console.WriteLine($\"a < b: {a = b: {a >= b}\"); // false // 小于等于 Console.WriteLine($\"a <= b: {a <= b}\"); // true }}
c#运算符优先级
using System;class Program{ static void Main() { int a = 5; int b = 3; int c = 2; // 先计算乘法,再计算加法 int result1 = a + b * c; Console.WriteLine($\"a + b * c 的结果: {result1}\"); // 先计算括号内的加法,再计算乘法 int result2 = (a + b) * c; Console.WriteLine($\"(a + b) * c 的结果: {result2}\"); // 逻辑与运算符优先级高于逻辑或运算符 bool condition1 = true || false && false; Console.WriteLine($\"true || false && false 的结果: {condition1}\"); // 加括号改变运算顺序 bool condition2 = (true || false) && false; Console.WriteLine(\"(true || false) && false 的结果: {condition2}\"); }}
三元运算符
控制流
控制流是编程中用于控制程序执行顺序的机制,主要包括条件语句、循环语句和跳转语句。
条件语句
条件语句用于根据条件决定是否执行某段代码。
1.1 if
语句
int age = 18;if (age >= 18){ Console.WriteLine(\"You are an adult.\");}
1.2 if-else
语句
int age = 16;if (age >= 18){ Console.WriteLine(\"You are an adult.\");}else{ Console.WriteLine(\"You are a minor.\");}
1.3 if-else if-else
语句
int score = 85;if (score >= 90){ Console.WriteLine(\"Grade: A\");}else if (score >= 80){ Console.WriteLine(\"Grade: B\");}else if (score >= 70){ Console.WriteLine(\"Grade: C\");}else{ Console.WriteLine(\"Grade: D\");}
1.4 switch
语句
在 C# 里,switch
语句的控制表达式(也就是 switch
后面括号中的变量)所支持的数据类型如下:
整数类型
包含 sbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
以及 char
类型。这些类型的值可以直接用在 switch
语句中。
using System;class Program{ static void Main() { int number = 2; switch (number) { case 1: Console.WriteLine(\"The number is 1.\"); break; case 2: Console.WriteLine(\"The number is 2.\"); break; default: Console.WriteLine(\"The number is neither 1 nor 2.\"); break; } }}
枚举类型
自定义的枚举类型也能在 switch
语句里使用。
using System;// 定义一个枚举类型enum Weekday{ Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}class Program{ static void Main() { Weekday today = Weekday.Monday; switch (today) { case Weekday.Monday: Console.WriteLine(\"It\'s Monday.\"); break; case Weekday.Tuesday: Console.WriteLine(\"It\'s Tuesday.\"); break; // 其他情况可依次添加 default: Console.WriteLine(\"It\'s another day.\"); break; } }}
字符串类型
从 C# 7.0 起,switch
语句支持字符串类型。
using System;class Program{ static void Main() { string color = \"Red\"; switch (color) { case \"Red\": Console.WriteLine(\"The color is red.\"); break; case \"Blue\": Console.WriteLine(\"The color is blue.\"); break; default: Console.WriteLine(\"The color is neither red nor blue.\"); break; } }}
可为空值类型
如果上述支持的类型是可为空值类型(例如 int?
、string?
等),同样可以在 switch
语句中使用。
using System;class Program{ static void Main() { int? nullableNumber = 2; switch (nullableNumber) { case 1: Console.WriteLine(\"The number is 1.\"); break; case 2: Console.WriteLine(\"The number is 2.\"); break; case null: Console.WriteLine(\"The number is null.\"); break; default: Console.WriteLine(\"The number is neither 1 nor 2.\"); break; } }}
模式匹配(C# 7.0 及更高版本)
从 C# 7.0 开始,switch
语句支持模式匹配,能对更多类型和条件进行匹配。
using System;class Program{ static void Main() { object obj = 2; switch (obj) { case int i when i < 5: Console.WriteLine($\"The integer is less than 5: {i}\"); break; case string s: Console.WriteLine($\"The string is: {s}\"); break; default: Console.WriteLine(\"The object is of another type.\"); break; } }}
不支持的类型
浮点类型
float
和 double
类型不适合用于 switch
语句,这是因为浮点数在计算机中是以二进制近似表示的,存在精度问题。例如,两个理论上相等的浮点数在计算机中可能由于精度误差而不相等,这样就无法准确匹配 case
标签。
using System;class Program{ static void Main() { double num = 0.1 + 0.2; // 由于精度问题,这里的比较可能不会按预期工作 switch (num) { case 0.3: Console.WriteLine(\"The number is 0.3\"); break; default: Console.WriteLine(\"The number is not 0.3\"); break; } }}
在这个例子中,尽管数学上 0.1 + 0.2
等于 0.3
,但由于浮点数精度问题,switch
语句可能不会匹配到 case 0.3
。
引用类型(除字符串)
一般的引用类型(如自定义类、数组等)不支持直接用于 switch
语句,因为引用类型比较的是引用地址而非值本身。不过,字符串类型是个例外,从 C# 7.0 开始支持在 switch
语句中使用。
using System;class MyClass{ public int Value { get; set; }}class Program{ static void Main() { MyClass obj1 = new MyClass { Value = 1 }; MyClass obj2 = new MyClass { Value = 1 }; // 以下代码会报错,因为 MyClass 类型不能直接用于 switch 语句 // switch (obj1) // { // case obj2: // Console.WriteLine(\"Objects are equal\"); // break; // default: // Console.WriteLine(\"Objects are not equal\"); // break; // } }}
布尔类型以外的逻辑类型
除了布尔类型,像 bool?
(可为空的布尔类型)可以在 switch
中使用外,其他逻辑相关的自定义类型如果没有合适的转换机制,也不能直接用于 switch
语句。
动态类型
dynamic
类型也不能直接用于 switch
语句,因为在编译时无法确定 dynamic
类型的具体值,switch
语句需要在编译时确定可能的 case
标签。
using System;class Program{ static void Main() { dynamic value = 1; // 以下代码会报错,因为 dynamic 类型不能用于 switch 语句 // switch (value) // { // case 1: // Console.WriteLine(\"Value is 1\"); // break; // default: // Console.WriteLine(\"Value is not 1\"); // break; // } }}
示例 1:简单的 switch
语句
int day = 3;switch (day){ case 1: Console.WriteLine(\"Monday\"); break; case 2: Console.WriteLine(\"Tuesday\"); break; case 3: Console.WriteLine(\"Wednesday\"); break; default: Console.WriteLine(\"Invalid day\"); break;}
输出:
Wednesday
示例 2:多个 case
共享代码块
int month = 2;switch (month){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: Console.WriteLine(\"31 days\"); break; case 4: case 6: case 9: case 11: Console.WriteLine(\"30 days\"); break; case 2: Console.WriteLine(\"28 or 29 days\"); break; default: Console.WriteLine(\"Invalid month\"); break;}
输出:
28 or 29 days
示例 3:switch
与字符串
string fruit = \"Apple\";switch (fruit){ case \"Apple\": Console.WriteLine(\"It\'s an apple.\"); break; case \"Banana\": Console.WriteLine(\"It\'s a banana.\"); break; default: Console.WriteLine(\"Unknown fruit.\"); break;}
输出:
It\'s an apple.
switch
语句与模式匹配
using System; class Program{ static void Main(string[] args) { int score; Console.Write(\"请输入学生的分数:\"); score = Convert.ToInt32(Console.ReadLine()); string grade; switch (score) { case int n when (n >= 90 && n = 80 && n = 70 && n = 60 && n < 70): grade = \"及格\"; break; default: grade = \"不及格\"; break; } Console.WriteLine(\"学生的成绩分类为:\" + grade); }}
switch
表达式(C#8.0及以上)
using System;class Program{ static void Main(string[] args) { int score; while (true) { Console.Write(\"请输入学生的分数:\"); if (int.TryParse(Console.ReadLine(), out score) && score >= 0 && score = 90 and \"优秀\", >= 80 and \"良好\", >= 70 and \"中等\", >= 60 and \"及格\", _ => \"不及格\" }; Console.WriteLine(\"学生的成绩分类为:\" + grade); }}
循环语句
循环语句用于重复执行某段代码,直到满足特定条件。
2.1 for
循环
for (int i = 0; i < 5; i++){ Console.WriteLine(\"Iteration: \" + i);}
2.2 while
循环
int i = 0;while (i < 5){ Console.WriteLine(\"Iteration: \" + i); i++;}
2.3 do-while
循环
int i = 0;do{ Console.WriteLine(\"Iteration: \" + i); i++;} while (i < 5);
2.4 foreach
循环
string[] fruits = { \"Apple\", \"Banana\", \"Cherry\" };foreach (string fruit in fruits){ Console.WriteLine(fruit);}
跳转语句
跳转语句用于改变程序的执行顺序。
3.1 break
语句
- 用于退出循环或
switch
语句。
for (int i = 0; i < 10; i++){ if (i == 5) { break; // 退出循环 } Console.WriteLine(\"Iteration: \" + i);}
3.2 continue
语句
- 用于跳过当前循环的剩余部分,直接进入下一次循环。
for (int i = 0; i < 10; i++){ if (i % 2 == 0) { continue; // 跳过偶数 } Console.WriteLine(\"Iteration: \" + i);}
3.3 return
语句
- 用于从方法中返回值并退出方法。
int Add(int a, int b){ return a + b;}int result = Add(3, 5); // result = 8
3.4 goto
语句
- 用于跳转到指定的标签(不推荐使用,容易导致代码混乱)。
int i = 0;start:if (i < 5){ Console.WriteLine(\"Iteration: \" + i); i++; goto start; // 跳转到 start 标签}
第二部分:面向对象编程(OOP)
类与对象
通过程序观察初步认识面向对象编程
using System;// 定义一个简单的类class Person{ // 字段 private string name; private int age; // 构造函数 public Person(string name, int age) { this.name = name; this.age = age; } // 方法 public void Introduce() { Console.WriteLine($\"我叫 {name},今年 {age} 岁。\"); }}class Program{ static void Main() { // 创建对象 Person person = new Person(\"张三\", 25); // 调用对象的方法 person.Introduce(); }}
类与对象的产生使用和组成规范
-
方法
- 方法的定义与调用
- 参数传递:值传递与引用传递(
ref
,out
) - 方法重载
-
访问修饰符
public
,private
,protected
,internal
- 封装的概念
-
继承
- 基类与派生类
base
关键字- 方法重写:
override
,virtual
-
多态
- 抽象类与抽象方法:
abstract
- 接口:
interface
- 接口与抽象类的区别
- 抽象类与抽象方法:
-
静态成员
- 静态字段与静态方法
- 静态类
static
关键字的使用场景