这里写目录标题
1. 数据类型
1.1 整型
- 创建变量的语法
<类型> <变量名> = <值>;
- int
- 举例:
int age = 25;
- long
- 举例:
long bigNumber = 1234567890123456789;
- short
- 举例:
short smallNumber = 123;
- char
- 举例:
char letter = 'A';
- byte(8位无符号整数)
- 举例:
byte singleByte = 255;
- bool
- 举例:
bool isAlive = true;
1.2 枚举
- 语法
- 定义
public enum <枚举类型>
{
<枚举值1>,
<枚举值2>,
...
}
- 创建枚举变量
<枚举类型> <变量名> = <枚举类型>.<枚举值>;
- 举例
public enum DayOfWeek
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
DayOfWeek today = DayOfWeek.Monday;
1.3 浮点
- float
- 举例:
float price = 19.99f;
- double
- 举例:
double highPrecision = 3.141592653589793;
1.4 可遍历的类型
1.4.1 数组
- 举例
int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
1.4.2 列表
- 举例
using System.Collections.Generic;
List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");
List<float> fList = new() { 3.1F, 3.2F };
1.4.3 字典
- 举例
using System.Collections.Generic;
List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");
Dictionary<string, int> siDic = new()
{
["abcd"] = 4,
["efg"] = 3
};
1.5 结构、类
1.5.1 结构
- 举例
struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
// 不使用 new,直接赋值
Point p1;
p1.X = 10;
p1.Y = 20;
// 使用 new 调用构造函数
Point p2 = new Point(30, 40);
// 或者直接初始化
Point p3 = new Point { X = 50, Y = 60 };
1.5.2 类
- 举例
class MyClass
{
public int Value;
public MyClass(int value)
{
Value = value;
}
}
// 使用 new 创建类的实例
MyClass obj = new MyClass(10);
1.5.3 对比
-
class:
- 属于引用类型,存储在堆内存中。
- 支持继承,可以定义析构函数。
- 适合存储较大的对象或需要频繁共享的对象。
-
struct:
- 属于值类型,一般存储在栈内存中(虽然 struct 是值类型,但在某些情况下,如存储在引用类型中或装箱时,它仍然会被分配在堆内存中)。
- 局部变量:通常分配在 栈内存 中。
- 作为引用类型的一部分:分配在 堆内存 中。
- 作为类的字段:分配在 堆内存 中。
- 装箱:分配在 堆内存 中。
- 不支持继承,不能定义析构函数。
- 适合存储较小的对象或频繁创建和销毁的对象。
- 属于值类型,一般存储在栈内存中(虽然 struct 是值类型,但在某些情况下,如存储在引用类型中或装箱时,它仍然会被分配在堆内存中)。
-
构造函数用于初始化对象,析构函数(仅适用于 class)用于清理资源,但通常可以通过实现 IDisposable 接口来更安全地管理资源。
1.6 关于 new 的使用
1.6.1 什么情况下使用 new
- 数组:必须使用 new 来分配内存。
- 结构体(struct):可以使用 new 来调用构造函数,但也可以直接赋值。
- 类(class):必须使用 new 来创建实例。
- 值类型(如 int, float 等):不需要使用 new,直接赋值即可。
- 字符串(string):可以使用 new 或直接赋值。
1.6.2 关于 new 的语法
- 调用 类、结构 的构造函数时,使用 ()
- 也可以使用 对象初始化器 {}
1.7 隐式类型推断
在某些情况下,C# 允许省略显式类型声明,使用 var 关键字进行隐式类型推断。编译器会根据赋值表达式推断出变量的类型。
class MyClass
{
public int Value;
public string Name;
}
struct MyStruct
{
public int X;
public int Y;
}
void Method()
{
// 使用 var 进行隐式类型推断
var obj = new MyClass(10); // 编译器推断 obj 的类型为 MyClass
var s = new MyStruct(1, 2); // 编译器推断 s 的类型为 MyStruct
// 使用 var 和对象初始化器
var obj2 = new MyClass { Value = 20, Name = "Moonshot" };
// 使用 var 和匿名类型
var anon = new { Value = 30, Name = "Anonymous" }; // 匿名类型
}
2. 条件语句
2.1 if - else if - else
if (condition1)
{
// 条件1为 true 时执行的代码
}
else if (condition2)
{
// 条件2为 true 时执行的代码
}
else
{
// 所有条件都不满足时执行的代码
}
2.2 switch
2.2.1 基础语法
switch (expression)
{
case value1:
// 表达式等于 value1 时执行的代码
break;
case value2:
// 表达式等于 value2 时执行的代码
break;
default:
// 默认情况下执行的代码
break;
}
2.2.2 when (C# 7.0+)
- switch 语句支持 when 关键字,用于在 case 中添加额外的条件。
int dayOfWeek = 3;
switch (dayOfWeek)
{
case 1 when (dayOfWeek > 0):
Console.WriteLine("Monday");
break;
case 2 when (dayOfWeek > 0):
Console.WriteLine("Tuesday");
break;
case 3 when (dayOfWeek > 0):
Console.WriteLine("Wednesday");
break;
default:
Console.WriteLine("Invalid day");
break;
}
2.2.3 swich 表达式(C# 8.0+)
int dayOfWeek = 3;
string dayName = dayOfWeek switch
{
1 => "Monday",
2 => "Tuesday",
3 => "Wednesday",
4 => "Thursday",
5 => "Friday",
6 => "Saturday",
7 => "Sunday",
_ => "Invalid day"
};
Console.WriteLine(dayName);
2.3 三元运算符 (xx ? xx : xx)
condition ? value1 : value2;
2.4 合并 空赋值 运算(??=)(C# 8.0+)
- 判断值是否为空,为空则赋值
- 举例1
string myString = null;
// 如果 myString 为 null,则赋值为 "default"
myString ??= "default";
Console.WriteLine(myString); // 输出:default
- 举例2
funcItemToStr ??= item => $"{item}";
- 解析
-
funcItemToStr:
这是一个变量,类型为委托(例如:ItemToStr<T>),它可能为 null。 -
??=:
这是空合并赋值运算符。它的作用是:
如果 funcItemToStr 当前为 null,则将其赋值为右侧的表达式。
如果 funcItemToStr 不为 null,则不进行任何操作。 -
item => $“{item}”:
这是一个 Lambda 表达式,表示一个委托,接受一个参数 item,并返回其字符串表示形式。
-
3. 循环
在 C# 中,循环语句用于重复执行一段代码,直到满足某个条件为止。C# 提供了多种循环语句,包括 for
、while
、do-while
和 foreach
。以下是对这些循环语句的详细说明和示例:
3.1 for
循环
for
循环是最常用的循环语句,适用于已知循环次数的情况。
- 语法:
for (初始化; 条件; 迭代器)
{
// 循环体
}
- 示例:
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i); // 输出 0 到 4
}
3.2 while
循环
while
循环用于在条件为 true
时重复执行代码块。如果条件为 false
,则不执行循环体。
- 语法:
while (条件)
{
// 循环体
}
- 示例:
int i = 0;
while (i < 5)
{
Console.WriteLine(i); // 输出 0 到 4
i++;
}
3.3 do-while
循环
do-while
循环与 while
循环类似,但 do-while
循环会至少执行一次循环体,即使条件为 false
。
- 语法:
do
{
// 循环体
} while (条件);
- 示例:
int i = 0;
do
{
Console.WriteLine(i); // 输出 0 到 4
i++;
} while (i < 5);
3.4 foreach
循环
foreach
循环用于遍历集合(如数组、列表等)中的每个元素。它不需要显式地管理索引。
- 语法:
foreach (类型 变量 in 集合)
{
// 循环体
}
- 示例:
int[] numbers = { 1, 2, 3, 4, 5 };
foreach (int number in numbers)
{
Console.WriteLine(number); // 输出 1 到 5
}
3.5 break
和 continue
-
break
:用于退出当前循环。 -
continue
:用于跳过当前循环的剩余部分,直接进入下一次迭代。 -
示例:
for (int i = 0; i < 10; i++)
{
if (i == 5)
{
break; // 退出循环
}
Console.WriteLine(i); // 输出 0 到 4
}
for (int i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
continue; // 跳过偶数
}
Console.WriteLine(i); // 输出 1, 3, 5, 7, 9
}
3.6 goto
语句
虽然不推荐使用,但 goto
语句可以用于跳转到指定的标签。它在某些特殊场景下(如状态机)可能有用。
- 示例:
int i = 0;
start:
if (i < 5)
{
Console.WriteLine(i); // 输出 0 到 4
i++;
goto start;
}
4. 函数、委托、泛型
4.1 函数
4.1.1 全局方法(C# 9.0+)
-
全局方法的位置
全局方法必须定义在文件的顶层,不能嵌套在类或结构体中。它们通常位于文件的开头部分。 -
全局方法的作用域
全局方法的作用域是整个文件,但它们只能在定义它们的文件中使用。全局方法不能被其他文件直接访问。 -
举例
using System;
// 全局方法
void PrintMessage(string message)
{
Console.WriteLine(message);
}
public class Program
{
public static void Main()
{
PrintMessage("Hello from global method!"); // 调用全局方法
}
}
4.1.2 类、结构 的成员函数
- 举例
public class MyClass
{
public void MyMethod()
{
Console.WriteLine("Hello from MyClass!");
}
}
public class Program
{
public static void Main()
{
MyClass obj = new MyClass();
obj.MyMethod(); // 调用类中的方法
}
}
4.1.3 函数中定义函数(局部函数)
- 举例
public class Program
{
public static void Main()
{
int CalculateSum(int a, int b)
{
return a + b;
}
int result = CalculateSum(5, 3);
Console.WriteLine(result); // 输出 8
}
}
4.1.4 匿名函数 & lambda 表达式
-
匿名函数:一种没有名称的函数,用于委托的实现。
-
Lambda 表达式:一种更简洁的匿名函数语法,用于委托或事件处理。
-
预定义的委托类型
- Action:预定义的委托类型,表示没有返回值的方法。
- Func:预定义的委托类型,表示有返回值的方法。
-
举例
using System;
public class Program
{
public static void Main()
{
Action myAction = delegate ()
{
Console.WriteLine("Hello from anonymous method!");
};
myAction(); // 调用匿名方法
// 使用 Lambda 表达式
Action myLambda = () => Console.WriteLine("Hello from Lambda!");
myLambda(); // 调用 Lambda 表达式
}
}
4.2 自定义委托
- 用于定义方法的签名,可以将方法作为参数传递,实现回调和事件处理。
- 类似于 c++ 中的 函数指针
- 举例
using System;
using System.Collections.Generic;
// 定义一个委托,表示对一个整数的操作
public delegate void ProcessItem(int item);
public class Program
{
// 一个方法,接受一个列表和一个委托
public static void ProcessList(List<int> list, ProcessItem process)
{
foreach (int item in list)
{
process(item); // 调用委托
}
}
// 一个具体的方法,用于打印整数
public static void PrintItem(int item)
{
Console.WriteLine(item);
}
public static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// 将 PrintItem 方法赋给委托
ProcessItem process = PrintItem;
// 调用 ProcessList 方法,传入委托
ProcessList(numbers, process);
}
}
4.3 泛型
- 用于定义通用的类、方法或接口,通过类型参数实现类型安全和代码复用。
- 类似于 c++ 中的模板
- 举例
void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}