学习刘铁猛老师《C#语言入门详解》视频,针对其中重点知识点进行总结。

1、什么是类型?

类型又称为数据类型(Data Type),数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作。

可以简单理解为数据在内存中存储的“型号”;小内存容纳大尺寸数据会丢失精准度,发生错误;而大内存容纳小尺寸数据会导致浪费。

还应注意编成语言的数据类型与数学中的数据类型不完全相同,例如数学中 3/4=0.75 而在C# 语言中 3 /4 =0。

不同的编程语言对数据类型的约束程度不一样,所以有强类型编程语言和弱类型编程语言的区分。

变量是用来存储值得所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。

我们都知道,计算机的世界是二进制的,仅仅用0和1就构建了所有的表达,计算机用来存储0或者1的单位就是位(bit),8个位组成一个字节(byte)。

2、数据类型在C#语言中的作用

一个C#类型中所包含的信息有:

  • 存储此类型变量所需的内存空间大小 如 int 类型需要4个字节也就是4*8=32位进行存储
  • 此类型的值可表示的最大、最小值范围 sbyte占一个字节8位,s前缀表示带符号位,取值范围-128到127,byte占一个字节,不带符号位,取值范围位0-255。
  • 此类型所包含的成员(如方法、属性、事件等) 可以用于ide的错误识别和反射时动态调用
  • 此类型由何基类派生而来
  • 程序运行的时候,此类型的变量在分配在内存的什么位置(栈或堆)
  • 此类型所允许的操作(运算)

3、程序的内存使用分析

  • Stack简介:函数调用使用,函数调用实际可以理解位栈帧的入栈出栈操作。空间较小,一般1-2M
  • Stack overflow 空间较小所以会出现栈空间溢出的情况。例如递归函数未正常结束。
  • Heap简介:用来存储对象(实例)使用,空间较大,可以达到数G
  • 使用Perfomance Monitor观察内存使用情况
  • 关于内存泄漏 未使用的对象未赋值为null导致垃圾收集器未处理,导致空间浪费,这称为内存泄漏。

这里给出观察内存使用情况的一个样例,新增的wpf程序,使用Winform程序也是可行的。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace HeapSample
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} List<Window> winList; private void Btn_Consume_Click(object sender, RoutedEventArgs e)
{
winList = new List<Window>();
for (int i = ; i < ; i++)
{
Window wd = new Window();
winList.Add(wd);
}
} private void Btn_ClearHeap_Click(object sender, RoutedEventArgs e)
{
winList.Clear();
}
}
}

至于Perfomance Monitor观察内存使用情况,可以查看 https:////www.cnblogs.com/FreeLoopPowter/p/12298482.html

4、C# 数据类型系统

C#的五大数据类型

  • 类(class):如 Form,Window,Console.String
  • 结构体(structres):如 Int32,Int64,SIngle,Double
  • 枚举(Enumerations):如Visibility,WindoState
  • 接口(Interfaces)
  • 委托(Delegate)

C#类型的派生谱系

这里顺带提一点,我们经常在编辑器中使用结构体时,例如定义一个32位的整型变量时,我们基本使用 int a=5; 这样的形式,这并不是前面说的结构体类型包含的内容,为啥没有报错呢?

这是由于某些数据类型如此常用,以至于许多编辑器允许代码以简化语法来操纵它们(也叫关键字)。这种语法不仅增强了代码的可读性和书写的方便性,生成的IL代码还与使用对应的FCL类库中的类型一致。

这类编译器能直接支持的类型称为 基元类型。基元类型直接映射到Framework类库(FCL)中存在的类型,可以通过按 F12 查看定义,就可以看到映射的FCL类型。

查看CLR Via C#一书,发现其对值类型和引用类型的阐述非常明了,还包括了对值类型和引用类型内存分配的讲解。这里选取重要内容进行记录,方便自己后续温习。对数据类型的内存分配情况的分析有利于后续理解方法的传值参数、引用参数、输出参数的理解。

CLR支持两种类型:引用类型和值类型。虽然FCL的大多数类型都是引用类型,但程序员使用最多的还是值类型。引用类型总是从托管堆中分配,C#的new 操作符返回对象内存地址——即指向对象数据的内存地址。使用引用类型必须留意性能问题,首先认清楚以下四个事实。

  • 内存必须从托管堆分配。
  • 堆上分配的每个对象都有一些额外成员。
  • 对象中的其他字段(为字段而设)总是设为零。
  • 从托管堆分配对象时,可能强制执行一次垃圾回收。(当垃圾回收器发现内存不够时会强制执行一次垃圾回收)

如果所有类型都是引用类型,应用程序的性能将显著下降。设想每次使用 Int32 时都进行一次内存分配,性能会收到多么大的影响!为了提升简单和常用的数据类型的性能,CLR提供了名为“值类型”的轻量级类型。值类型的实例一般是在线程栈上分配(虽然也可作为字段嵌入引用类型的对象中),在代表值类型实例的变量中不包含指向实例的指针。变量中包含了实例本身的字段。由于变量已包含了实例的字段,所以操作实例中的字段不需要提取指针。值类型的实例不受垃圾回收器的控制。因此,值类型的使用缓解了托管堆的压力,并减少了应用程序生存期间的垃圾回收次数。

下面给出一个示例,结合图示讲解值类型和引用类型的区别。引用类型变量对对象实例的引用实际上是以在栈中分配的引用类型变量存放堆中实例的起始内存地址来实现的。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace RefTypeAndValueTypeApp
{
class Program
{
static void Main(string[] args)
{
//在堆上分配空间
SomeRef r1 = new SomeRef();
//在栈上分配空间
SomeValue v1 = new SomeValue();
r1.x = ;//提取指针,给指针引用的对象赋值
v1.x = ;//在栈上修改,由0修改为5
Console.WriteLine(r1.x);//显示 "5"
Console.WriteLine(v1.x);//同样显示 "5"
//以上内存分配情况见图左边 //只复制引用(指针)
SomeRef r2 = r1;
//在栈上分配并复制成员
SomeValue v2 = v1;
r1.x = ;//r1.x 和 r2.x 都会改变
v1.x = ;//v2.x会改变 v1.x不会改变
Console.WriteLine(r1.x);//显示 "8"
Console.WriteLine(r2.x);//同样显示 "8"
Console.WriteLine(v1.x);//显示 "9"
Console.WriteLine(v2.x);//显示 "5"
//以上部分程序执行的内存分配情况见图右侧 //让控制台等待输入,有输入后才终止
Console.ReadKey();
}
}
/// <summary>
/// 引用类型
/// </summary>
class SomeRef
{
public Int32 x;
} /// <summary>
/// 值类型
/// </summary>
struct SomeValue
{
public Int32 x;
}
}

书写这篇随笔的主要目的是自己温习和防遗忘,本着分享的心态公开,如有不妥之处,还请指出,相互交流。

C# 数据类型详解以及变量、对象与内存的更多相关文章

  1. Python之路-变量和基本数据类型详解(变量、数据类型、)

    一.注释 注释的作用: 增加程序的可读性 作为调试用 提高团队的合作效率 注释的分类 1.单行注释 以井号(#)开头,右边的所有内容当做说明 2.多行注释 以三对单引号(’’’注释内容’’’)将注释包 ...

  2. 详解Go变量类型的内存布局

    定义 每当我们编写任何程序时,我们都需要在内存中存储一些数据/信息.数据存储在特定地址的存储器中.内存地址看起来像0xAFFFF(这是内存地址的十六进制表示). 现在,要访问数据,我们需要知道存储它的 ...

  3. c# 把一个匿名对象赋值给一个Object类型的变量后,怎么取这个变量? c# dynamic动态类型和匿名类 详解C# 匿名对象(匿名类型)、var、动态类型 dynamic 深入浅析C#中的var和dynamic

    比如有一个匿名对象,var  result =......Select( a=>new {  id=a.id, name=a.name});然后Object  obj =  result ;我怎 ...

  4. 2-2和2-3基本数据类型 & 2-4基本数据类型详解 & 3-1和3-2整形字面量值及变量声

    2-4基本数据类型详解 3-1和3-2整形字面量值及变量声 023是八进制的 0x1357是十六进制 0X3C也是十六进制 0x1abL:长整型 变量声明 数据类型 空格 变量名 赋值: 变量的定义:

  5. python 数据类型详解

    python数据类型详解 参考网址:http://www.cnblogs.com/linjiqin/p/3608541.html 目录1.字符串2.布尔类型3.整数4.浮点数5.数字6.列表7.元组8 ...

  6. python数据类型详解(全面)

    python数据类型详解 目录1.字符串2.布尔类型3.整数4.浮点数5.数字6.列表7.元组8.字典9.日期 1.字符串1.1.如何在Python中使用字符串a.使用单引号(')用单引号括起来表示字 ...

  7. 转 python数据类型详解

    python数据类型详解 目录 1.字符串 2.布尔类型 3.整数 4.浮点数 5.数字 6.列表 7.元组 8.字典 9.日期 1.字符串 1.1.如何在Python中使用字符串 a.使用单引号(' ...

  8. 详解js变量、作用域及内存

    详解js变量.作用域及内存 来源:伯乐在线 作者:trigkit4       原文出处: trigkit4    基本类型值有:undefined,NUll,Boolean,Number和Strin ...

  9. python之数据类型详解

    python之数据类型详解 二.列表list  (可以存储多个值)(列表内数字不需要加引号) sort s1=[','!'] # s1.sort() # print(s1) -->['!', ' ...

随机推荐

  1. 【红外DDE算法】数字细节增强算法的缘由与效果(我对FLIR文档详解)

    [红外DDE算法]数字细节增强算法的缘由与效果(我对FLIR文档详解) 1. 为什么红外系统中图像大多是14bit(甚至更高)?一个红外系统的性能经常以其探测的范围来区别,以及其对最小等效温差指标.首 ...

  2. 调试 ambari-server 总结

    刚开始debug ambari-server的时候,很多逻辑都是第一次接触.其中有很多知识点还是记录一下的好,做个备忘.这些知识点对于自定义api的开发还是很有作用的. 1. api的子href的最后 ...

  3. 4、python基础语法

    前言:本文主要介绍python的一些基础语法,包括标识符的定义.行和缩进.引号和注释.输入输出.变量的定义. 一.标识符 1.凡是我们自己取的名字,都是标识符. 2.在Python里,标识符由字母.下 ...

  4. 学习 lind api 十月 第一弹

    step one 我们来看一下代码的结构

  5. [HNOI2008]明明的烦恼(prufer序列,高精度,质因数分解)

      prufer序列 定义 Prufer数列是无根树的一种数列.在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2. 描述 eg 将 ...

  6. Django 2.2

    Django 2.2 LTS 发布,长期支持版来了 django中文网:https://www.django.cn/course/course-3.html Django 2.2 已正式发布,这是一个 ...

  7. apache和nginx那点事儿--阻塞和异步

    先明白的事儿:当一个程序在执行的时候,一般会创建一个进程,也可以有多个进程.一个进程至少会创建一个线程,多个线程共享一个程序进程的内存.程序的运行最终是靠线程来完成操作的.线程的数量跟CPU核数有关, ...

  8. git---如何在远程某个分支的基础上新建分支

    问题场景 技术主管让你去再某个git分支上新建一个分支去做你的项目,那么如何在原远程分支的基础上新建自己的分支呢? 解决方法 按照以下命令敲即可 git branch newBranch //新建本地 ...

  9. mac安装了anaconda但是在终端不能使用conda命令

    只需在终端输入如下命令即可 export PATH=~/anaconda3/bin:$PATH

  10. JDK源码之StringBuffer与StringBuilder类分析

    一 概述 StringBuffer类被 final 所修饰,不能被继承,StringBuffer继承了AbstractStringBuilder类, 是一个可变的字符序列,并且类中方法都有synchr ...