C#引用类型与值类型的比较

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using SimpleDelegate.Models;
  6 using System.Data.SqlClient;
  7 using System.Data;
  8 namespace SimpleDelegate
  9 {
 10     class Program
 11     {
 12         static void Main(string[] args)
 13         {
 14             int i = 1;
 15             Tools.TryChange(i);             //no-change
 16            
 17             int j = 2;
 18             Tools.Swap(i, j);               //no-swap
 19             Tools.Swap(ref i,ref j);        //swap
 20             
 21             List<object> l1 = new List<object>() { 1,2 };
 22             Tools.TryChange(l1);            //change
 23 
 24             List<object> l2 = new List<object>() { 88 };
 25             Tools.Swap(l1,l2);              //no-swap
 26             Tools.Swap(ref l1,ref l2);      //swap
 27             
 28             Console.Read();
 29         }  
 30     }
 31 
 32     public class Tools
 33     {
 34         /// <summary>
 35         /// 输出任意实现IEnumerable迭代器的集合包括Array,List,IQueryable,普通数组等
 36         /// 调用本方法时可不指定T类型。因为带参数ienum,编译器会自动判断
 37         /// </summary> 
 38         public static void OutputEnumable<T>(IEnumerable<T> ienum)
 39         {
 40             foreach (T item in ienum)
 41             {
 42                 Console.WriteLine(item);
 43             }
 44         }
 45 
 46         /// <summary>
 47         /// 输出多个参数至终端
 48         /// </summary>
 49         public static void OutputParams(params object[] paras)
 50         {
 51             Console.WriteLine(OutputParamsToString(paras));
 52         }
 53 
 54         /// <summary>
 55         /// 拼接多个参数至字符串
 56         /// </summary>
 57         public static string OutputParamsToString(params object[] paras)
 58         {
 59             StringBuilder sb = new StringBuilder();
 60             foreach (object item in paras)
 61             {
 62                 sb.Append(item + ",");
 63             }
 64             return sb.ToString();
 65         }
 66 
 67         /*****************************测试**************************/
 68 
 69         /// <summary>
 70         /// 交换值或引用类型变量。更改成功,原因
 71         /// 1.值类型:传入原值,就在原值处修改
 72         /// 2.引用类型,传入原指针,更改原来的两个指针的值(存有指向数据的地址)
 73         /// </summary>
 74         public static void Swap<T>(ref T value1, ref T value2)
 75         {
 76             T tmp = value1; value1 = value2; value2 = tmp;
 77         }
 78 
 79         /// <summary>
 80         ///  试图交换两值,结果无效,原因
 81         ///  1.值类型:传入值副本,在内存中重新开辟两int空间存数字,函数结束后原来两值未变
 82         ///  2.引用类型,传入地址,可以理解为指向数据的指针副本,在内存中重新开辟两空间存指针,函数结束后原来两值所指向的数据未变
 83         /// </summary>
 84         public static void Swap<T>(T value1, T value2)
 85         {
 86             T tmp = value1; value1 = value2; value2 = tmp;
 87         }
 88 
 89         public static void TryChange(int i)
 90         {
 91             i = 7;
 92         }
 93 
 94         /// <summary>
 95         /// 有效,使用指针向数据区添加新数据,指针本身值不变
 96         /// </summary>
 97         public static void TryChange(List<object> l)
 98         {
 99             l.Add(2);
100         }
101 
102     }
103 }

另外补上值类型与引用类型在==与Equals()的区别

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using SimpleDelegate.Models;
 6 using System.Data.SqlClient;
 7 using System.Data;
 8 using System.IO;
 9 using System.Xml.Serialization;
10 namespace SimpleDelegate
11 {
12     class Program
13     {
14         static void Main(string[] args)
15         {
16             //MSDN关于==的解释
17             //对于预定义的值类型,如果操作数的值相等,则相等运算符 ( ==) 返回 true,否则返回 false。
18             //对于 string 以外的引用类型,如果两个操作数引用同一个对象,则 == 返回 true。
19             //对于 string 类型, == 比较字符串的值。
20             string s1 = "123";
21             string s2 = "123";
22             Console.WriteLine(s1 == s2);      //true,比较值
23             Console.WriteLine(s1.Equals(s2)); //true,比较值
24 
25             Box redBox = new Box(8, 8, 4);
26             Box blueBox = new Box(6, 8, 4);
27             Box greenBox = new Box(8, 8, 4);
28             Console.WriteLine(redBox == greenBox);    //false,不引用同一对象,可理解为比较内部存的数据区域地址
29             //调用类型内部自定义的比较器
30             Console.WriteLine(redBox.Equals(greenBox)); //true,比较W,L,H值都相等
31 
32             Console.Read();
33         }
34         public class Box : IEquatable<Box>
35         {
36             public int Height { get; set; }
37             public int Length { get; set; }
38             public int Width { get; set; }
39 
40             public Box(int h, int l, int w)
41             {
42                 this.Height = h;
43                 this.Length = l;
44                 this.Width = w;
45             }
46 
47             /// <summary>
48             /// 用户自定义比较器,需H,L,W全部相等才对象相等
49             /// </summary>
50             public bool Equals(Box other)
51             {
52                 #region MSDN关于&的解释
53                 //一元 & 运算符返回操作数的地址(要求 unsafe 上下文)。
54                 //为整型和 bool 类型预定义了二进制 & 运算符。
55                 //对于整型,& 计算操作数的逻辑按位“与”。
56                 //对于 bool 操作数,& 计算操作数的逻辑“与”;也就是说,当且仅当两个操作数均为 true 时,结果才为 true。 
57                 #endregion
58                 if (this.Height == other.Height & this.Length == other.Length
59                     & this.Width == other.Width)    //&在此等同于&&
60                 {
61                     return true;
62                 }
63                 else
64                 {
65                     return false;
66                 }
67             }
68         }
69     }
70 }

大家直接看代码吧,有什么不懂先运行下,看后理解下。最后再查查资料吧。

C#中的值类型保存在栈中引用类型保存在堆中。

C#中有两类重要类型:1.值类型(数字等),继承自ValueType,2.引用类型(类),继承自object。

具体可以参见http://www.cnblogs.com/niyw/archive/2010/09/20/1832077.html

C#是高级语言,有些地方内部难以了解,故原理、揭秘很重要。

原文地址:https://www.cnblogs.com/nlh774/p/3483972.html