关于c#值类型和引用类型

来源:互联网 发布:淘宝发信息给客服不回 编辑:程序博客网 时间:2024/05/17 06:07

      记得在刚开始学习c#的时候,就会接触到值类型和引用类型,当时对这两者之间的区别不是特别清楚。现在互联网上关于这两者之间的区别的文章很多,一般说下来有以下几点。

     1. 值类型主要是由结构和枚举类型组成,这里面的结构还包括整型,浮点型等系统预定义类型和用户自定义的结构类型。值类型的变量直接包含实例值,其值是直接存储在内存的堆栈上的,故使用值类型的效率会比较高 。引用类型的变量保存的实例在内存中地址,其将实例的地址存储在内存的堆栈上。因此基于这点区别,在复制值类型的变量时,直接是将变量完全拷贝,拷贝结束之后,两个变量之间即没有了任何关系。而引用类型则只是复制了实例的地址,两个变量所对应的实例的地址还是一样的,当实例的值发生变化时,这两个变量所表示的值也相应的发生变化。

     2. 值类型是不能派生的,故不能被继承。

     3. 值类型不能赋值为null,但是如果该值类型被定义为可空类型时,则可以为null

下面的代码简要描述一下:

 

 1 private void TestRef()
 2{
 3            int num1 = 1;
 4            int num2 = num1;
 5            string str1 = "a";
 6            string str2 = str1;
 7            Console.Write(" num1:{0}/n num2:{1}/n str1:{2}/n str2:{3}/n",num1,num2,str1,str2);
 8
 9            num1 = 2;
10            str1 = "b";
11            Console.Write("===========================================/n");
12            Console.Write(" num1:{0}/n num2:{1}/n str1:{2}/n str2:{3}/n", num1, num2, str1, str2);
13 }
输出结果:
 num1:1 num2:1 str1:a str2:a
======================
num1:2 num2:1 str1:b str2:b
接下来可以看一下关于ref,out以及普通的传参之间的区别:
先看下代码:
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4
 5namespace Practice
 6{
 7    public class Cs_Ref
 8    {
 9
10        public void GetValue(string str, int num)
11        {
12            str = "test";
13            num = 11;
14        }

15
16        public void GetValue(ref string str, ref int num)
17        {
18            str = "test";
19            num=11;
20        }

21
22        public void GetValue(out int num, out string str)
23        {
24            str = "test";
25            num = 11;
26        }
 
27
28    }

29}

 1        private void TestRef()
 2        {
 3            int num1 = 1;
 4            int num2 ;
 5            string str1 = "a";
 6            string str2;
 7
 8            Cs_Ref cs = new Cs_Ref();
 9            Console.Write("==============================/n");
10            cs.GetValue(str1,num1);
11            Console.Write("num1:{0}/n str1:{1}/n",num1,str1);
12
13            cs.GetValue(ref str1, ref num1);
14            Console.Write("==============================/n");
15            Console.Write("num1:{0}/n str1:{1}/n", num1, str1);
16
17            cs.GetValue(out num2, out str2);
18            Console.Write("==============================/n");
19            Console.Write("num2:{0}/n str2:{1}/n", num2, str2);
20            
21            Console.ReadLine();
22        }
输出结果:
num1:1 str1 :a
===================
num1:11 str1:test
===================
num2:11 str2: test
故由上代码执行可知,在一般的传参的时候,并不改变实参之前的值,类似于拷贝值类型的特点,即实参的值不会因为所执行的方法而进行改变
而通过ref关键字之后可以看见,实参的值会因为所执行的方法而改变
out关键字则是在执行方法之前,实参可以不必赋值。