目录
基本数据类型
C#的数据类型采用了类似于C和C++语言的数据类型描述形式,但又有所改进。C#将所有的数据类型分成两大类:值类型 引用类型。
1.值类型
※值类型通常用来表示简单类型、结构类型、枚举类型。
C#的值类型主要包括:整数类型 布尔类型 实数类型 字符类型 结构类型 枚举类型
1.1 整数类型
C#提供了八种整型(即计算机组成原理中的“定点数”):sbyte、byte、short、ushort、int、uint、long、ulong
数据类型 | 特征 | 取值范围 |
sbyte | 有符号8位整数 | -128~127 |
byte | 无符号8位整数 | 0~255 |
short | 有符号的16位整数 | -32768~32767 |
ushort | 无符号的16位整数 | 0~65535 |
int | 有符号的32位整数 | -2 147 482 648~2 147 483 647 |
uint | 无符号的32位整数 | 0~4 294 967 295 |
long | 有符号的64位整数 | -9 223 372 036 854 775 808~9 223 372 036 854 775 807 |
ulong | 无符号的64位整数 | 0~18 446 744 073 709 551 615 |
1.2 布尔类型
用bool表示,bool类型只有两个值true和false。 例如:
bool isExist = false;
bool b = (i>0 && i<10);
//注意
if(i) j += 10;//错误
if(j = 15) j += 10; //错误
1.3 实数类型
float:4字节浮点数,常用。例如:35.0f;double:8字节浮点数,常用。例如:2.7E+23;decimal:16字节浮点数,特殊的浮点数,精度高,适用于金融、货币等需要高精度数值的领域。其类型指定符为M(或m)。 例如: decimal y = 99999999999999999m;
类型 | 大致范围 | 精度 |
float | ±1.5 × 10-45 到 ±3.4 × 1038 | 7 位 |
double | ±5.0 × 10-324 到 ±1.7 × 10308 | 15 到 16 位 |
decimal | ±1.0 × 10-28 到 ±7.9 × 1028 | 28 到 29 位有效位 |
1.4 字符型
C#提供字符(char)处理ASCII字符和Unicode编码的字符。
① ASCII字符是美国标准委员会提供的,采用7位二进制表示的字符。
②Unicode是国际标准化组织制定的采用16位二进制表示的字符,它可以表示世界上大多数语言。
③字符常量是用单引号(即撇号)括起来的一个字符。如:'a'、'x'、'D'、'? '、'$'和'1'都是字符常量。注意,'a'和'A'是不同的字符常量。
④C#还允许用一种特殊形式的字符常量,就是以一个“\”开头的字符序列。例如,'\n'表示一个换行符,它代表一个“换行”符。这种非显示字符难以用一般形式的字符表示,故规定用这种特殊形式表示。
转义序列 | 字符名称 | Unicode编码 |
\' | 单引号 | 0x0027 |
\" | 双引号 | 0x0022 |
\\ | 反斜杠 | 0x005C |
\0 | 空 | 0x0000 |
\a | 警报 | 0x0007 |
\b | 退格符 | 0x0008 |
\n | 换行符 | 0x000A |
\r | 回车 | 0x000D |
1.5 结构类型
有时需要将不同类型的数据组合成一个有机的整体以便使用,例如要编制一个学生信息管理系统,对全校学生的信息进行管理,一个学生具有学号、姓名、性别、年龄、地址等信息,如果使用简单数据类型分布存储这些信息的话,很难完成反映出这些信息的内在联系,所以应该将它们组织成一个整体。
①C#语言提供了结构类型(structure),允许用户根据实际的需要实现特定的数据类型。
②示例:例如学生信息管理,我们必须将一个学生的学号、姓名、性别、年龄、地址信息组合成一个新的数据类型,我们可以采用如下形式:
struct Student
{
public int No; // 记录学号信息
public string Name; // 记录学生姓名
public char sex; // 学生性别
public int Age; // 学生年龄
public string Addr; // 学生的地址
};
1.6 枚举类型
在程序设计中,有时会用到由若干个有限数据元素组成的集合,可将这些数据集合定义为枚举类型(enum)。
枚举类型定义的一般形式为: enum 枚举名 { 枚举值表 };
在枚举值表中应罗列出所有可用值,这些值也称为枚举元素。
示例1: enum Weekday{sun, mon, tue, wed, thu, fri, sat};该枚举名为Weekday,枚举值共有7个,即一周中的七天。
按照系统默认,枚举中的每个元素的类型都是整型类型,且第1个元素的值为0,后面的元素按照加1递增。当然也可以给元素之间赋值,例如:
enum Weekday
{sun=1, mon=4, tue, wed, thu, fri, sat};
这样sun的值为1,mon的值为4,tue的值为5,以后值按照加1递增。
示例2: enum 节气
{
立春, 雨水, 惊蛰, 春分, 清明, 谷雨, 立夏, 小满, 芒种, 夏至, 小暑, 大暑, 立秋, 处暑, 白露, 秋分, 寒露, 霜降, 立冬, 小雪, 大雪, 冬至, 小寒, 大寒
}
//语句调用
节气 SolarTerms =节气.秋分;
Console.WriteLine(SolarTerms);
2.引用类型
一个引用类型的变量不存储它们所代表的实际数据,而是存储实际数据的引用。引用类型分两步创建:首先在堆栈上创建一个引用变量,然后在堆上创建对象本身,再把这个内存的句柄(也是内存的首地址)赋给引用变量。
例如:
string s1, s2;
s1="ABCD"; s2 = s1;
其中,s1,s2是指向字符串的引用变量,s1的值是字符串“ABCD”存放在内存的地址,这就是对字符串的引用,两个引用型变量之间的赋值,使得s2、s1都是对“ABCD”的引用。如图所解。
在C#中提供以下引用类型:类类型(class);字符串类型(string);数组类型(array);接口类型(interface);委托类型(delegate);object
2.1 类类型
类是面向对象编程的基本单位,它是一种包含数据成员,函数成员和嵌套类型的数据结构。类的数据成员有常量,域和事件,函数成员包括方法,属性,索引指示器,运算符,构造函数和析构函数,有关类的深入讲述将在以后的学习中介绍。
2.2 字符串类型
在C#中有一个用于操作字符串数据的基本字符串类型,字符串类直接派生自对象,且它是被密封的,这意味着再不能从它派生类。就像其它类型,字符串是预定义类System String的一个别名。它的用法十分简单:
string myString = "绿水青山就是金山银山";
2.3 数组类型
同C语言一样,C#语言中也有数组类型,但是与C语言中数组概念相比有了很大扩展。一个数组包含有通过计算下标访问的变量,所有包含于数组中且被当作元素的变量必须是同一类型。这种类型自然被称为"数组类型"。
让我们看一下用一个数组初始化器初始化的数组:
string[] arrLanguages = { "C", "C++", "C#" };
该简写效果等同以下:
arrLanguages[0]="C"; arrLanguages[1]="C++"; arrLanguages[2]="C#";
2.4 接口类型
一个接口是一个只有抽象成员的引用类型。C#中的接口只有方法名,但这些方法没有执行代码 。
下面我们定义一个接口IFace,它只有一个方法:
interface IFace
{
void ShowMyFace();
}
2.5 委托类型
C#中的委托类型和C/C++中的函数指针非常相似,C#中的委托类型有一个特性就是不需要知道被引用的方法属于那一个类对象,只要函数的参数个数与返回值与委托类型对象中的一致就可以了 。
定义一个委托类型,该类型名为delegate string MyDelegate();
下面定义一个类MyClass,该类中包含一个名为SayHello的方法,请注意,该方法与我们上面声明的委托类型具有相同的参数个数和返回值。
public class MyClass
{
public string SayHello()
{
return "Hello the world!";
}
}
我们定义一个测试类TestMyClass
public class TestMyClass
{
public static void Main(string[] args)
{
MyClass myClass1=new MyClass();
MyDelegate myDelegate1=new MyDelegate(myClass1.SayHello);
//下面就使用myDelegate1代替对象myClass1的SayHello方法
System.Console.WriteLine(myDelegate1());
//输出结果为hello the world! 与调用myClass1.SayHello();效果相同
}
}
2.6 Object类型
object 类型在 .NET Framework 中是 Object 的别名。在 C# 的统一类型系统中,所有类型(预定义类型、用户定义类型、引用类型和值类型)都是直接或间接从 Object 继承的。可以将任何类型的值赋给 object 类型的变量。将值类型的变量转换为对象的过程称为“装箱”。将对象类型的变量转换为值类型的过程称为“取消装箱”。
值类型和引用类型的区别:
特性 | 值类型 | 引用类型 |
变量中保存的内容 | 实际数据 | 指向实际数据的引用指针 |
内存空间配置 | 堆栈(Stack) | 受管制的堆(Managed Heap) |
内存需求 | 较少 | 较多 |
执行效率 | 较快 | 较慢 |
内存释放时间点 | 执行超过定义变量的作用域时 | 由垃圾回收机制负责回收 |
可以为null | 不可以 | 可以 |
2.7 值类型之间的数据转换
有两种转换方式:隐式转换与显式转换。如果是不同值类型之间的转换,可以使用Convert类。
①隐式转换:从低精度、小范围的数据类型转换为高精度、大范围的数据类型,可以用隐式转换。例如:
int k = 1;
long i = 2;
i = k; //隐式转换
②显示转换,如:
long k = 5000;
int i = (int)k;
所有的隐式转换也都可以采用显式转换的形式来表示。如:
int i = 10;
long j = (long)i;
将大范围类型的数据转换为小范围类型的数据的时候,必须特别谨慎,因为此时有丢失数据的危险。
2.8 装箱与拆箱
①装箱:将值类型包装成引用类型的处理过程。当一个值类型被要求转换成一个object对象时,装箱操作自动进行,它首先创建一个对象实例,然后把值类型的值复制到这个对象实例,最后由object对象引用这个对象实例。例如:
using System;
class Demo
{
public static void Main ( )
{
int x = 123;
object obj1=x; // 装箱操作
x = x+100; // 改变x的值,此时obj1的值并不会随之改变
Console.WriteLine (" x= {0}" , x ); // x=223
Console.WriteLine (" obj1= {0}" , obj1 ); // obj1=123
}
}
②拆箱:拆箱操作与装箱相反,它是将一个object类型转换成值类型。首先检查由object引用的对象实例值类型的包装值,然后把实例中的值拷贝到值类型的变量中。例如:
class Demo
{
public static void Main ( )
{
int x = 123, y;
object obj1=x; // 装箱操作
x = x+100; // 改变x的值,此时obj1的值并不会随之改变
y = (int) obj1; // 拆箱操作,必须进行强制类型转换
Console.WriteLine (" x= {0}" , x ); // x=223
Console.WriteLine (" obj1= {0}" , obj1 ); // obj1=123
}
}