C#程序在运行的过程中,处理数据处理,还有数据存储,现有数据才能进行操作
在上一章的代码中,主函数的参数有个string[] arg
这个表示类型为string
数组的变量arg
其中这个arg
就是一个用于数据存储的容器,你可以往里面读取或者写入数据
在存储数据之前,我们需要先知道需要能存什么数据
在C#语言中,默认会提供一些数据类型,这与编程入门里面的数据类型类似但更具体
- byte/sbyte 1字节整型,其中的sbyte表示有符号
- ushort/short 2字节整型,其中的ushort表示无符号
- uint/int 4字节整型,其中的uint表示无符号
- ulong/long 8字节整型,其中的ulong表示无符号
- float 4字节浮点型
- double 8字节浮点型
- bool 布尔类型,只有true与false
- char 字符,一般2字节
- string 字符串,可以储存多个字符组合起来的东西
- unint/nint 指针,一般8字节
除此之外,还有以下类型
- 各种类class 是的类也算类型,通常以object为基底
- 各种记录类型record 与类相似的东西
- 各种结构体struct 与C语言里面的结构体相似
- 各类枚举enum
- 各类元组类型 例如(int, byte)由多种数据类型组合形成的类型
- 各类 ref 结构类型 表示结构体放在堆栈中,而不是托管堆,可以先不用理解这个
- 各类数组 类似xxx[]的
例如前面的实例代码中Console
其实也是一种类型
字符串一般是类似"123"
,而字符一般是类似'a'
整数一般为123
或者456
,当你输入数字后,大部分情况默认会是int
类型,如果你需要指定为long
类型,你可以输入123L
表示这个123
是long
类型
浮点数也是类似,通常输入为double
类型,若需要float
类型可以输入2.0f
指针类型就是内存指针
,一般也是整数,但是储存的内容是内存地址,一般使用的时候会做特殊处理,这个指针与C语言的指针类似
有了数据类型,我们就可以开始将数据按照某个形式存储了,你可以选择存在变量
或者常量
里面
变量
故名思意,就是一个内容可以变化的容器,但变化只能变化值,不能变化类型
而常量
就是类型跟内容都不能变化的盒子
变量与常量在使用前需要声明,例如
类型 变量名;
类型 变量名=数值;
const 类型 常量名=数值;
有一种特殊的情况下,声明的变量类型可以变换
dynamic 变量名;
使用dynamic
作为类型,此时变量里面的值和类型都可以随意变换,且会帮你判断类型并做处理,也就是相当于没有类型了,但是不推荐使用,性能会大幅度下降
在代码中,声明一般是这样写
namespace ConsoleApp1;
internal class Program
{
static void Main(string[] args)
{
int a; //声明一个变量a类型为int
const int b = 0; //声明一个常量b类型为int,值为0
}
}
声明的位置可以不在函数内,在类里面也可以
namespace ConsoleApp1;
internal class Program
{
int a; //声明一个变量a类型为int
const int b = 0; //声明一个常量b类型为int,值为0
static void Main(string[] args)
{
}
}
但是不能在命名空间里面声明
常量在声明的同时,需要给它赋予一个初始值,否则会产生错误
在一些地方,声明变量时有可能为了方便会使用var
来表示变量,类型编译器会自动判断
var a = 1; //声明一个类型为int的变量a
var b = true; //声明一个类型为bool的变量b
var c = 1.0f; //声明一个类型为float的变量c
//var d; //错误,无法知道类型
变量还可以配合readonly
来表示这个是一个只读变量,意思是只能赋值一次
在无法赋值常量时,但你又想只能设置一次,可以使用readonly
来实现
一般用法
//const List<int> a = []; //错误,List没有常量的形式存在
readonly List<int> a = []; //声明一个只读变量a类型为List<int>,初始值为0
常量与变量的赋值,很简单,左边
等于右边
,左边为变量或者常量,右边为需要给的值
左边 = 右边;
namespace ConsoleApp1;
internal class Program
{
const int b = 0; //声明一个常量b类型为int,值为0
int a; //声明一个变量a类型为int
static void Main(string[] args)
{
a = 1; //给变量a赋值1
//b = 0; //不允许,常量不允许赋值
a = b; //给变量a赋值常量b的值,也就是0
a = a; //给变量a赋值a的值,也就是不变
}
}
注意:变量在使用前,需要先有个值,例如
namespace ConsoleApp1;
internal class Program
{
int a; //声明一个变量a类型为int
int b; //声明一个变量b类型为int
static void Main(string[] args)
{
//a = b; //给变量a赋值变量b的值,但是错误,因为b没有默认值
}
}
namespace ConsoleApp1;
internal class Program
{
int a; //声明一个变量a类型为int
int b = 0; //声明一个变量b类型为int,默认值0
static void Main(string[] args)
{
a = b; //给变量a赋值变量b的值,为0
}
}
变量在赋值的时候,只能赋值同类型,或者低级类型
如果非要赋值,需要使用强制转换操作
int a; //声明一个变量a类型为int
int b = 0; //声明一个变量b类型为int,默认值0
long c = 1; //声明一个变量b类型为long,默认值1
float d; //声明一个变量d类型为float
double e = 3; //声明一个变量e类型为double,默认值3
byte f = 2; //声明一个变量f类型为byte,默认值2
a = b; //给变量a赋值变量b的值,为0
//a = c; //给变量a赋值变量c的值,不允许,因为long长度比int大,不是低级类型
a = f; //给变量a赋值变量f的值,为2
d = b; //给变量d赋值变量b的值,为0
//d = e; //给变量d赋值变量e的值,不允许,因为double长度比float大,不是低级类型
d = (float)e; //给变量d赋值变量e的值,强制转换为d类型
总的来说,就是大的给不了小的,小的可以给大的,若需要给小的,需要进行强制转换,但转换会丢失数据
例如doubel->int
会丢失小数部分,只保留整数部分
int->byte
会丢失大于byte的部分,也就是范围小了会截取
给变量赋值,可以选择输入的进制
int a = 89; //给变量a赋值10进制的值89
int b = 0x55; //给变量b赋值16进制的值0x55=85
int c = 0b11; //给变量c赋值2进制的值0b11=3
C#中还有一种类型叫做可空类型,意识是里面的数据有可能为null,其声明方式为类型?
int? a = null; //声明一个int可空变量a,初始数据为null
double? b = 1.0; //声明一个double可空变量b,初始数据为1.0
string? c = "123"; //声明一个string可空变量b,初始数据为"123"
使用可空类型一般用于你不确定数据是否存在的情况下,不存在直接给null
就可以了
注意:int
与int?
不是一个东西,操作方式会有区别,请使用时需要注意
在某些地方,你需要一个足够大的容器来存储数据,你有两种做法
逐一变量声明
int a1 = 0;
int a2 = 0;
int a3 = 0;
int a4 = 0;
int a5 = 0;
int a6 = 0;
int a7 = 0;
...
int a20 = 0;
或者使用数组
int[] a = new int[20]; //定义一个数组变量,名字为a,类型为int,长度为20
显然是使用数组
更方便
数组在定义时,需要决定类型
与长度
数组里面的内容称为元素
,数组的第几个就代表第几个元素
数组一旦定义后,类型与长度均不可以改变,里面的元素会给类型的默认值
关于类型的默认值,可以参考C# 类型的默认值(C# 参考)
定义数组时,可以传递初始值
int[] b = new int[20] = {1, 2, 3, 5, 6}; //定义一个数组变量,名字为b,类型为int,长度为20,且前几个元素
定义时长度,可以是一个变量,但需要保证执行顺序
int a = 20;
int[] b = new int[a]; //定义一个数组变量,名字为b,类型为int,长度为a,因为a为20,所以长度为20
访问数组的内容可以使用变量名[下标]
例如
int[] a = new int[20];
a[0] = 1; //给数组的第1个赋值1
int b = a[1]; //获取数组的第2个值
访问数组时,下标从0开始,也就是第1个下标为0 当访问超出范围时会报错
int[] a = new int[20];
a[20] = 0; //报错,访问范围超出