本节内容是对于C#基础类型的存储方式以及C#基础类型的理论介绍git
例如如下这句话:“张三是一名程序员,今年15岁重50.3kg,他的代号是‘A’,他家的经纬度是(N30,E134)。”,这句话就是一个字符串,使用双引号括起来。而15则表示是一个 整数类型,50.3就是小数类型,不过咱们在C# 中一般称为 浮点类型,最后一个经纬度,咱们一般定位地点的时候都是成对出现,因此咱们认为这两者是一个密不可分的结构,这种类型咱们称为 结构体类型(struct)。程序员
以上我所说的数据类型都是一个所含有信息量必定的数值,咱们称为值类型;而张三这我的,他所含有的数据大小是不固定的,好比我又了解到了张三是一个富二代,那么他就会增长一个属性是富二代,咱们须要更多的空间去存储他,张三这个变量咱们一般就称为引用类型,而张三这个名字,咱们就称为引用,若是你对C或者C++熟悉的话,张三这个名字就是指向张三这我的(对象)的一个指针。github
在C# 中,数据在内存中的存储方式主要分为在堆中存储和栈中存储。咱们以前提到的值类型就是存储在栈中,引用类型的数据是存储在堆中,而数据是在栈中。编程
值类型:存储在栈(Stack,一段连续的内存块)中,存储遵循先进后出,有严格的顺序读取访问速度快,可经过地址推算访问同一个栈的其他变量。数组
引用类型:引用(本质上和C++中的指针一致)存储在栈中,内含的数据存储在堆中(一大块内存地址,内部变量存储不必定连续存储)。安全
(此处须要补充堆栈图片)编程语言
事实上,值类型和引用类型有一个很明显的区别就是值类型应当都是有值的,而引用类型是能够为空值的。ide
数组:继承自Array类,属于任意类型的一种集合,但不一样于集合,大小必须被初始化。在内存中是一段连续的内存空间,可是不是值类型。函数
int number = 5;//定义一个32位整数类型 bool b = true;//定义 //注意看如下两条,string定义的字符串必须为双引号,而char使用单引号而且只容许输入一个字符 string str = "test"; char a = 'a'; //记得后缀 float f = 1.3f; decimal d = 1.5m;
数据类型的转换分为隐式转换和显式转换,看下面几个例子:学习
string a = "15"; int b = int.Parse(a);//显式转换 b = (int)a;//强制转换 b = Convert.ToInt32(a);//显式转换,较经常使用 double d = 1.5; b = d;//隐式转换
数组指一个类型(任意)的集合,例如你定义一个变量为a=5,很轻松,假设你须要100个呢?所以咱们使用数组来存储。
数组的定义以及使用以下:
///伪代码,T为类型,n为大小 T [] t = new T[n]; //定义一个整型数组 int [] a = new int [5]; //你也能够选择初始化的方式定义 int [] b = new int [] {1,2,3,4,5}; //或 int [] c = new int [5]{1,2,3,4,5}; //数组的访问,从0开始索引 Console.WriteLine(b[0]);
具体的操做我会在我在BiliBili上发布的.Net Core教程上进行详细的讲述。
结构体你能够理解为将将若干个类型拼接在一块儿,可是存在一个很重要的内容——内存对齐。例以下面两个结构体:
struct S { int a; long b; int c; } struct SS { int a; int b; long c; }
乍一看你会以为这两个结构体彻底一致,丝毫没有任何的差异。但事实上,在大多数编程语言里面,对于结构体这种大小并非定值的值类型,都存在一个最小分配单元用于结构体内单个变量的大小分配。在内存中,他们两个的存储方式有很大的不一样。
对于上面两个结构体,他们在内存中的单元分配是:
在C#中,若是你不指定最小分配单元,那么编译器将会把结构体中占用内存最大的做为最小分配单元。不过尤为须要注意一件事,就是引用类型在结构体中。鉴于咱们如今还没有讲解面向对象的类,咱们用string做为成员写一个结构体。以下面这个例子:
struct S { char a; long b; string c; } //函数中建立 S s = new S(); s.a = 'a'; s.b = 15; s.c = "I Love .NET Core And Microsoft"
很显然s.c的大小超过告终构体中其他两个,可是内存分配的时候就是以最大的c做为标准吗?
显然不是,咱们要知道struct是在栈中分配内存,string的内容是在堆中的,因此在结构体中存储的string只是一个引用,并不会包含其余的东西,只占用4个字节。而且特别的,引用类型在内存中的位置位于大于四字节的字段前,小于四字节字段后。
上面内存分配应当是这样:
a(8) --> c(8) --> b(8)。
若是须要深刻了解这一方面内容,建议去阅读《CLR Via C#》这本书,以及学习SOS调试相关内容。
更多内容请关注个人BiliBili地址以及个人博客。
Github上有练习题、实例代码以及ppt。
若是我帮到了你,请在个人Github点上一颗星,一个fork。谢谢,地址Github