规则与C语言相同,在此不再赘述
C#的值类型可以分为简单类型、结构类型和枚举类型。
类型标识符 | 说明 | 占用位数 | 取值范围 | 示例 |
---|---|---|---|---|
sbyte | 带符号字节型 | 8 | -128~127 | sbyte i=10 ; |
byte | 无符号字节型 | 8 | 0~255 | byte i=10 ; |
short | 带符号短整型 | 16 | -32,768~32,767 | short i=10 ; |
ushort | 无符号短整型 | 16 | 0~65,535 | ushort i=10 ; |
int | 带符号整型 | 32 | -2,147,483,648~2,147,483,647 | int i=10 ; |
uint | 无符号整型 | 32 | 0~4,294,967,295 | uint i=10 ;uint i=10U ; |
long | 带符号长整型 | 64 | -9,223,372,036,854,775,808~9,223,372,036,854,775,807 | long i=10 ;long i=10L ; |
ulong | 无符号长整型 | 64 | 0~18,446,744,073,709,551,615 | ulong i=16 ;ulong i=16U ;ulong i=16L ;ulong i=16UL ; |
类型标识符 | 说明 | 取值范围 | 示例 |
---|---|---|---|
float | 单精度浮点数 | ±1.5×10-45 ~2.4×1038,精度为7位数 | float f=1.23F ; |
double | 双精度浮点数 | ±5.0×10-324 ~1.7×10308,精度为15到16位数 | double d=1.23 ; |
decimal | 固定精度的浮点数 | 1.0×10-28到~7.9×1028的之间,精度为28至29位有效数字 | decimal d=1.23M ; |
可以采用如下方式字符变量赋值:
char c0 = 'A'; // 字符Achar
c1 = '\x0041'; // 字符A,十六进制转义符(前缀为\x)
char c2 = '\u0061'; // 字符a,Unicode表示形式(前缀为\u)
char c3 = '\r'; // 回车,转义字符
char c4 = '\u3234'; // 汉字“名”
Console.WriteLine("{0},{1},{2},{3},{4}", c0, c1, c2, c3, c4);
布尔类型数据用于表示逻辑真和逻辑假,布尔类型的类型标识符是bool。注意:在C#语言中,bool类型不能像C++语言那样可能直接转换为int类型。
例如,int a=(2<3);在C/C++中都是正确的,但在C#中不允许这样,会出现“无法将类型bool隐式转换为int”的编译错误。
引用类型也称为参考类型。和值类型相比,引用类型的变量不直接存储所包含的值,而是指向它所要存储的值。类似C中的指针。
object是C#中所有类型(包括所有的值类型和引用类型)的基类,C#中的所有类型都直接或间接地从object类中继承而来。因此,对一个object的变量可以赋予任何类型的值。具体理解可见下面的代码:
float f = 1.23F;object obj1; //定义obj1对象
obj1 = f;object obj2 = "China"; //定义obj2对象并赋初值
Console.WriteLine("{0},{1}", obj1, obj2);// 1.23,China
同样,这个类也是在.NET Framework的命名空间System中定义的,是类System.String的别名。
字符串在实际中应用非常广泛,利用string类中封装的各种内部操作,可以很容易完成对字符串处理。例如:
string str1 = "123" + "abc"; //"+"运算符用于连接字符串
char c = "Hello World!"[2]; //"[]"运算符可以访问string中的单个字符,c='l '
Console.WriteLine(c);
//string str2 = "China";
string str2 = "China\r\n";//\r表示回车
string str3 = @"China\r\n"; // 字符串的另一种表示形式,用@引起来。China\r\n
Console.WriteLine(str2);
Console.WriteLine(str3);
bool b = (str2 == str3); //"=="运算符用于两个字符串比较,b=true
结果如下图:
字符串插值语法在一个字符串字面量前加上一个$符号前缀,然后将表达式嵌入大括号中。
string person = $"id:{id}, name:{name},age:{age}";
字符串运算符只有一个,就是加号(+)。它除了作为算术运算符之外,还可以将字符串连接起来,变成合并的新字符串。例如:
String mstr = "1,2,dfdf,dkk";
string[] strs = mstr.Split(',');//用,把字符串分开
for(int i =0; i< strs.Length;++i)
{
Console.WriteLine(strs[i]);
}
C#类型 | .NET Framework类型 | C#类型 | .NET Framework类型 |
---|---|---|---|
bool | System.Boolean | uint | System.UInt32 |
byte | System.Byte | long | System.Int64 |
sbyte | System.SByte | ulong | System.UInt64 |
char | System.Char | object | System.Object |
decimal | System.Decimal | short | System.Int16 |
double | System.Double | ushort | System.UInt16 |
float | System.Single | string | System.String |
int | System.Int32 |
结构类型由若干“成员”组成的。
数据成员称为字段,每个字段都有自已的数据类型。声明结构类型的一般格式如下:
struct 结构类型名称 {
[字段访问修饰符] 数据类型 字段1;
[字段访问修饰符] 数据类型 字段2;
// …
[字段访问修饰符] 数据类型 字段n;
};
例如,以下声明一个具有姓名和年龄的结构体类型Student(不用在前面加typdef,加上会报错):
struct Student //声明结构类型
Student{
public int xh; //学号
public string xm; //姓名
public string xb; //性别
public int nl; //年龄
public string bh; //班号
};
另外,结构类型声明应放在Main函数的外面。
声明一个结构类型后,可以定义该结构类型的变量(简称为结构变量)。
定义结构变量的一般格式如下:
** 结构类型 结构变量;**
例如,在前面的结构类型Student声明后,定义它的两个变量如下:
Student s1,s2;5.3
1)访问结构变量字段
访问结构变量字段的一般格式如下:
结构变量名.字段名
例如,s1.xh表示结构变量s1的学号,s2.xm表示结构变量s2的姓名。
结构体变量的字段可以在程序中单独使用,与普通变量完全相同。
2)结构变量的赋值
结构变量的赋值有两种方式。
结构变量的字段赋值:使用方法与普通变量相同。
结构变量之间赋值:要求赋值的两个结构变量必须类型相同。
枚举类型也是一种自定义数据类型,它允许用符号代表数据。枚举是指程序中某个变量具有一组确定的值,通过“枚举”可以将其值一一列出来。
枚举类型使用enum关键字声明,其一般语法形式如下:
enum 枚举名 {枚举成员1,枚举成员2,¼}
其中,enum是结构类型的关键字。
例如,以下声明一个名称为color的表示颜色的枚举类型:
enum Color {Red,Green,Blue,White,Black}
在声明枚举类型后,可以通过枚举名来访问枚举成员,其使用语法如下:
枚举名.枚举成员
在声明的枚举类型中,每一个枚举成员都有一个相对应的常量值,默认情况下C#规定第1个枚举成员的值取0,它后面的每一个枚举成员的值按加1递增。
例如,前面Color中,Red值为0,Green值为1,Blue值为2,依次类推。
可以为一个或多个枚举成员赋整型值,当某个枚举成员赋值后,其后的枚举成员没有赋值的话,自动在前一个枚举成员值之上加1作为其值。
例如:
enum Color { Red=0, Green, Blue=3, White, Black=1};
则这些枚举成员的值分别为0、1、3、4、1。
声明一个枚举类型后,可以定义该枚举类型的变量(简称为枚举变量)。
定义枚举变量的一般格式如下:
枚举类型 枚举变量;
例如,在前面的枚举类型Color声明后,定义它的两个变量如下:
Color c1,c2;
1)枚举变量的赋值枚举变量赋值的语法格式如下:
枚举变量=枚举名.枚举成员
2)枚举变量的访问枚举变量像普通变量一样直接访问。
程序的内存空间分为栈空间和堆空间,值类型的数据在栈空间中分配,而引用类型数据(对象)在堆空间中分配。
程序的执行空间:栈空间和堆空间。
栈空间在一块连续的内存,是一种先进后出的数据结构,栈空间用于存储如下类型的数据:
(1)某些类型变量的值。
(2)程序当前的执行环境。
(3)传递给方法的参数。
堆空间是一块内存空间,在堆空间中可以分配大块的内存以存储某类型的数据对象。
C#中的值类型变量和C/C++语言中的普通变量(非指针变量)相似,这类变量直接包含它们的值。所有的值类型均隐式派生自 System.ValueType。
C#中在内存的栈空间中为值类型变量分配空间,而且没有单独的堆分配或垃圾回收开销。因此值类型变量会随着方法调用后栈空间的消亡而自动清除(C#中的值类型变量像C/C++语言中函数内的局部变量,函数执行完后由系统释放其存储空间)。例如:
int x;
int y = 2;
x = y;
在C#中没有指针,而改为引用,引用表示某个对象的地址而不是变量或对象本身。
在C#中,无论值类型变量还是引用类型变量,都是在栈空间中分配对应的存储空间,所不同的是,引用类型变量所指向的对象是在托管堆上分配内存空间的,为什么这样呢?
将C#应用程序的执行置于CLR的监控之下,而且所有引用类型变量所指向的对象(其生命周期是全局性的)都在托管堆上分配空间,程序执行完毕,由CLR将堆空间全部回收,这样就不会出现像前面C/C++程序出现的内存泄漏问题了。
所以在C#中,当定义一个引用类型变量时,系统在栈空间中为该引用变量分配存储空间,要想创建对象并把对象的存储地址赋给该变量,就需要使用new操作符。例如:
MyClass var; //MyClass是已定义的类或类型
var = new MyClass(); //创建var引用的实例
下面以数组引用类型变量为例进一步说明引用类型变量和值变量的区别:
int[] a = new int[3] { 1, 2, 3 }; //定义一个数组a
for (int i = 0; i < 3; i++) //输出数组a的所有元素
Console.Write("{0} ", a[i]);
Console.WriteLine();int[] b = a; //定义数组b并赋值为a
for (int i = 0; i < 3; i++) //修改数组b的元素
b[i] *= 2;
for (int i = 0; i < 3; i++) //再次输出数组a的所有元素
Console.Write("{0} ", a[i]);
Console.WriteLine();
隐式转换是系统默认的、不需要加以声明就可以进行的转换。
源类型 | 目标类型 |
---|---|
sbyte | short、int、long、float、double、decimal |
byte | short、ushort、int、uint、long、ulong、float、double、decimal |
short | int、long、float、double、decimal |
ushort | int、uint、long、ulong、float、double、decimal |
int | long、float、double、decimal |
uint | long、ulong、float、double、decimal |
long | float、double、decimal |
ulong | float、double、decimal |
char | ushort、int、uint、long、ulong、float、double、decimal |
float | double |
显示类型转换与C语言方法相同,这里不再赘述。
装箱:
int i=10;object obj=i;
拆箱操作分为两步:首先检查对象实例,确保它是给定值类型的一个装箱值,然后把实例的值复制到值类型数据中。例如,下面两条语句就执行了拆箱转换:
object obj=10;int i=(int)obj; //拆箱
几乎与C语言相同。
sizeof运算符求值类型数据在内存中占用的字节数。
sizeof运算符的语法格式如下:
sizeof(类型标识符)
其结果为一个整数,表示指定类型的数据在内存分配的字节数。该运算符只能作用于值类型或值类型变量。
该运算符用于获得指定数据类型的说明。
例如,若声明了结构Student,则以下语句输出声明Student结构类型的程序名等。
Console.WriteLine(typeof(Student)); // 输出:prog2_2.Program+Student
该运算符用于创建一个类的对象。
checked 关键字用于对整型算术运算和转换显式启用溢出检查。
unchecked 关键字用于取消整型算术运算和转换的溢出检查。