C# base
C艹艹,忘光光。
好像学Unity的时候,直接当作语法略有不同的C艹来写了。应该没问题吧。
先写点基础。
概述
见过的C#用在
- Unity游戏编程
- 服务器后端
数据类型
C#是语言,.NET是运行时平台。首先我想先遍历一下基本的数据类型,后面再好好了解背后的编译原理吧。
$
\begin{cases}
\text{值类型 (Value Types)} &
\begin{cases}
\text{预定义数值类型} &
\begin{cases}
\text{整型: sbyte, byte, short, ushort, int, uint, long, ulong} \\
\text{浮点型: float, double, decimal}
\end{cases} \\
\text{预定义非数值类型: bool, char} \\
\text{用户自定义: struct, enum}
\end{cases} \\\\
\text{引用类型 (Reference Types)} &
\begin{cases}
\text{预定义类型: object, string, dynamic} \\
\text{用户自定义: class, interface, delegate, Array}
\end{cases}
\end{cases}
$
值类型
整型
byte、short、int、long分别为1、2、4、8个字节长度。
其中表示有无符号的前缀,只有byte有个sbyte(即signed有符号的意思),其它的u起头,代表无符号
| C# 类型/关键字 | 范围 | 尺寸 | .NET类型 |
|---|---|---|---|
sbyte |
-128 到 127 | 8 位带符号整数 | System.SByte |
byte |
0 到 255 | 无符号 8 位整数 | System.Byte |
short |
-32,768 到 32,767 | 带符号 16 位整数 | System.Int16 |
ushort |
0 到 65,535 | 无符号 16 位整数 | System.UInt16 |
int |
-2,147,483,648 到 2,147,483,647 | 带符号的 32 位整数 | System.Int32 |
uint |
0 到 4,294,967,295 | 无符号 32 位整数 | System.UInt32 |
long |
-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 64 位带符号整数 | System.Int64 |
ulong |
0 到 18,446,744,073,709,551,615 | 无符号 64 位整数 | System.UInt64 |
nint |
取决于平台(在运行时计算) | 带符号 32 位或 64 位整数 | System.IntPtr |
nuint |
取决于平台(在运行时计算) | 无符号 32 位或 64 位整数 | System.UIntPtr |
比起C++,C#的整型大小固定、溢出可控、命名统一。
每个整型的默认值为零。 0
每个整型类型都有MinValue和MaxValue属性,用于提供该类型的最小值和最大值。
整数字面量
十进制、十六进制、二进制表示法:1
2
3var decimalLiteral = 42;
var hexLiteral = 0x2A;
var binaryLiteral = 0b_0010_1010;
浮点型
| C# 类型/关键字 | 近似范围 | 精准率 | 尺寸 | .NET 类型 |
|---|---|---|---|---|
float |
±1.5 x 10~45 到 ±3.4 x 1038 | ~6-9 位数字 | 4 个字节 | System.Single |
double |
±5.0 × 10~324 到 ±1.7 × 10308 | ~15-17 位数字 | 8 个字节 | System.Double |
decimal |
±1.0 x 10-28 到 ±7.9228 x 1028 | 28-29 位数字 | 16 字节 | System.Decimal |
布尔型
| 类型 | 范围 | 尺寸 | .NET 类型 |
|---|---|---|---|
bool |
true和false |
1 字节 | System.Boolean |
字符型
| 类型 | 范围 | 尺寸 | .NET 类型 |
|---|---|---|---|
char |
U+0000 到 U+FFFF | 16 位 | System.Char |
字符的定义方法可以是字符、unicode转义、十六进制转义
1 | var chars = new[] |
[!IMPORTANT]
- 在
Unicode转义序列中,必须指定4个十六进制数字。 也就是说,\u006A是有效的转义序列,而\u06A和\u6A无效。- 在十六进制转义序列中,可以省略前导零。
枚举
枚举都长差不多。默认int1
2
3
4
5
6
7enum Season
{
Spring,
Summer,
Autumn,
Winter
}
不按默认来:1
2
3
4
5
6
7enum ErrorCode : ushort
{
None = 0,
Unknown = 1,
ConnectionLost = 100,
OutlierReading = 200
}
总之差不多。
结构
struct,当C++用即可,后面学一下readonly
ref
元组
1 | (double, int) t1 = (4.5, 3); |
元组长度可以任意。可以用var定义。
可空类型
让值类型也可以null。做游戏时最爱用的一集(读入null中)。用法是在类型后面加一个?。
1 | double? pi = 3.14; |
不加问号不行1
int a = null; // 编译器:打咩哟!介是啥呀?
内置类型转换
- 任何整型数值类型都隐式转换为任何浮点数值类型
引用类型
字符串
字符串的常用成员
| 成员 | 类型 | 意义 |
|---|---|---|
Length |
属性 | 返回字符串的长度 |
Concat |
静态方法 | 返回连接多个参数字符串后的新字符串 |
Contains |
方法 | 返回子串是否出现在当前字符串 |
Format |
静态方法 | 返回根据格式字符串和参数格式化后的字符串 |
Insert |
方法 | 在指定位置插入指定字符串,返回新字符串 |
Remove |
方法 | 从当前字符串中移除指定范围的字符,返回新字符串 |
Replace |
方法 | 将当前字符串中的所有指定字符或子串替换为另一字符或子串,返回新字符串 |
Split |
方法 | 根据指定分隔符将,字符串分割为子字符串数组 |
Substring |
方法 | 提取指定起始位置和长度的子字符串 |
ToLower |
方法 | 返回小写副本 |
ToUpper |
方法 | 返回大写副本 |
字符串解析为数据值
Parse方法。
1 | string si = "25.873"; |
无法转换会抛出异常。
防止抛出异常,可以用TryParse
1 | string s = "28"; |
数组
System.Array
数组的声明
1 | type[] arrayName;//数组的声明 |
矩形数组与交错数组
与C/C++不同,C#数组可以长度不一,称为“交错数组”
1 | // 矩形数组 |
与其它语言比较,Python的“交错数组”就是嵌套列表(日常自由),Java本质上都是交错数组
1 | // Java |
数组的读写:
1 | // C#的读写 |
矩形数组有点像Python的这个
1 | # Python |
注意交错数组不能在声明语句中初始化顶层数组之外的数组
1 | // ❌错的 |
数组的常用方法
集合
类
详见后面“C#的面向对象”
接口
记录
record修饰符
(遇到了再学吧。)
看这里:https://www.cnblogs.com/shanfeng1000/p/14973804.html
1 | public record Person(string FirstName, string LastName); |
1 | public record Person |
void
非托管类型
默认值
默认值表
| 类型 | 默认值 | ||
|---|---|---|---|
| 引用类型 | null |
||
| 内置整数数值类型 | 0 |
||
| 内置浮点型数值类型 | 0 |
||
bool |
false |
||
char |
'\0' |
||
enum |
0 强制转换成该枚举类型(即使枚举中没有值为 0 的成员) |
||
struct |
将所有值类型字段设置为其默认值,将所有引用类型字段设置为null,生成的值。 |
||
可空值类型(T?) |
null(即 HasValue = false,没有有效值) |
默认值表达式
1 | int a = default; |
foreach
这是一个经典的foreach
1 | int[] myArr = new int[]{5, 6, 7}; |
foreach遍历时,只可读不可写。而且中途不能修改被遍历的可迭代对象(这里是myArr)
异步foreach
解构foreach
C#的面向对象
类
访问修饰符
6个 类成员的访问修饰符
| 修饰符 | 含义 | 类似 C++ | 类似 Java |
|---|---|---|---|
public |
都能访问 | public |
public |
private |
仅在同一类/结构体内可访问 | private |
private |
protected |
同一类+派生类可访问 | protected |
protected |
internal |
同一程序集(项目)内可访问 | 无直接对应(C++ 用internal链接属性) |
default(包级私有) |
protected internal |
同一程序集或派生类(跨程序集也行) | 无直接对应 | 无直接对应 |
private protected |
同一程序集内的派生类可访问(C# 7.2+) | 无 | 无 |
2个 顶级类的访问修饰符
1 | class MyInternalClass { } // 默认 internal,仅同一程序集内可见 |
顶级类下的嵌套类可以用6个类成员的访问修饰符
接口
命名空间
异常
try-catch
异步编程
吐槽
微软你个入机。。。
不过我写的也很入机就是了。
一个编程语言都没有深入学。
想横向学习各个编程语言的编译原理(都,编译了吗?)