zoukankan      html  css  js  c++  java
  • 值类型和引用类型

    在C#中值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中。

    常见的值类型数据有:整值型(整形,浮点型,十进制型),布尔类型,枚举类型;

    引用类型有:接口,数组,Object类型,类,委托,字符串,null类型。

    在C#中每种类型的存储方式有两种:1)分配在托管栈中;2)分配在托管堆中;

    内存的分配有CLR管理(即公共语言运行时),这两种方法的区别是:

    1)分配在托管栈中的变量会在创建它们的方法返回时自动释放,例如在一个方法中声明Char型的变量UserInput=C,当实例化它的方法结束时,UserInput变量在栈上占用的内存就会自动释放;

    2)分配在托管堆中的变量并不会在创建它们的方法结束时释放内存,它们所占用的内存会被CLR中的垃圾回收机制释放。

    看下面的代码:

    1 static void Main(string[] args)
    2         {
    3             //当nStudent声明并赋值是,这时在托管栈上就会开辟一块内存来存储nStudent的值,当实例化nStudent的Main()方法结束时,
    4             //nStudent在托管栈上占用的内存会自动释放。
    5             int nStudent = 0;
    6             //当声明strStuName时,这个时候“小明”存储在托管堆中,而托管栈中存储的是strStuName指向的引用。
    7             string strStuName = "小明";

    9             Console.WriteLine("学生的总数是{0},五号的名字是{1}", nStudent, strStuName);
    10             Console.ReadKey();
    11         }

    装箱和拆箱

    当值类型的数据转换成引用类型时,CLR会先在托管堆配置一块内存,将值类型的数据复制到这块内存,然后再让托管栈上的引用类型的变量指向这块内存,这样的过程称为装箱。相反的话,有引用类型转换成值类型的话就称为拆箱。

    一般情况下,.NET会主动的帮我们完成装箱操作,但是拆箱并非主动,我们必须知道拆箱对象的实力类型,然后明确的去执行拆箱操作。

    1 int BirthdayNum = 1989;
    2             object BoxBirthdayNum = BirthdayNum;//系统自动装箱
    3             int nBirthdayNum = (int)BoxBirthdayNum;//明确数据类型的拆箱

    因为花费了更多的时间,所以装箱和拆箱对程序的性能有一定的影响。

    --------------------------------------------------------------------------------------------------------------------------------------

    类型推断

    在C#中有两种类型的数据,一种是值类型,另一种是引用类型。

    值类型包括:内置值类型、用户自定义值类型、和枚举,如 int,float bool 等,以及struct等。

    引用类型包括接口类型、用户自定义的类、委托等。如 string 、DateTime、数组等。

    值类型是存储在堆栈中,而引用类型是存储在托管堆上,C#程序首先被编译成IL程序,然后在托管执行。值类型直接从堆栈中里面取值,而引用类型必须要先从堆栈里面取出它的地址,再根据这个地址在堆里找到对应的值。


    值类型与饮用类型的本质区别有以下几点:

    1.内存分配: 值类型是分配在栈中的;而引用类型是分配在堆中。

    2.效率: 值类型效率高,不需要地址转换;引用类型效率较低,需要进行地址转换。

    3.内存回收: 值类型使用完后立即回收;引用类型使用完后不立即回收,而是交给GC处理回收。

    4.赋值操作: 值类型是创建一个新对象;引用类型创建一个引用。

    5.类型扩展: 值类型不易扩展,所有值类型都是密封(seal)的,所以无法派生出新的值类型;引用类型具有多态的特性方便扩展。

    这是别人的总结,我在这里拿来用下。

    下面我在说说它们在用法上的区别了,C#之所以要分这两种数据类型的原因是达到更好的性能,把一些基本类型如int、bool规定为值类型,而把包含许多字段的较大类型规定为引用类型,如用户自定义的类。值类型主要是负责存储数据,引用类更多是用在代码的重用性上。

    从C#3.0开始,C#引入了一个隐式类型推断的关键字var,编译器可以通过它的初始值来判断变量的具体类型。var只能用于局部变量的声明,不能用于字段级的变量声明。使用var关键字时,var必须得有初始值,这样编译器才能判断是否是真实变量。

    1 class Program
    2     {
    3         static void Main(string[] args)
    4         {
    5             var i = 10;//隐式类型
    6             int m = 10;//显示类型

    8             var Program=new Program();
    9             Program.nAge = 20;
    10             Program.SayHello();
    11         }
    12 
    13         private int nAge;
    14         public void SayHello()
    15         {
    16             var message = "my age is {0}";
    17             Console.WriteLine(message, nAge);
    18         }
    19     }

    message初始值的变量为字符串类型,因此编译器可以推断其类型为String类型

  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/wuyuankun/p/3736749.html
Copyright © 2011-2022 走看看