值类型与引用类型的区别在于:值类型在赋值的时候是拷贝值,引用类型在赋值的时候的拷贝引用。记住这一个原则,我们再来分析一些具体情况:

             PointStruct pt1 = new PointStruct(,);
PointStruct pt2 = pt1;
PointStruct[] ptsArray = new PointStruct[];
ptsArray[] = pt1;
ptsArray[] = pt2;
List<PointStruct> ptsList = new List<PointStruct>();
ptsList.Add(pt1);
ptsList.Add(pt2);
List<PointStruct> pts2List = new List<PointStruct>();
pts2List.AddRange(ptsArray); List<PointStruct> pts3List = pts2List; Console.WriteLine("值类型的数组,原始值:");
Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
ptsArray[].X, ptsArray[].Y, ptsArray[].X, ptsArray[].Y));
Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
ptsList[].X, ptsList[].Y, ptsList[].X, ptsList[].Y));
Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
pts2List[].X, pts2List[].Y, pts2List[].X, pts2List[].Y));
Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
pts3List[].X, pts3List[].Y, pts3List[].X, pts3List[].Y));
pt2.X = ;
pt1.Y = -;
ptsArray[].X = ;
ptsArray[].Y = ;
ptsList[] = new PointStruct(, );
pts2List[] = new PointStruct(-, -);
Console.WriteLine("值类型的数组,修改后:");
Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
ptsArray[].X, ptsArray[].Y, ptsArray[].X, ptsArray[].Y));
Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
ptsList[].X, ptsList[].Y, ptsList[].X, ptsList[].Y));
Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
pts2List[].X, pts2List[].Y, pts2List[].X, pts2List[].Y));
Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
pts3List[].X, pts3List[].Y, pts3List[].X, pts3List[].Y));

其中PointStruct是一个值类型,我们先看结果:

从结果上可以看出来,值类型基本上都是各管各的,互不干扰,最后的pts2List与pts3List是同一个引用,所以修改其中任意一个是会影响另外一个的,数组,列表集合都会这样,因为其实就是同一个对象,只是取了2个名字而已,所以不管这个对象是否是值类型。

我们再看下面的代码:

             PointReference pt1 = new PointReference(, );
PointReference pt2 = pt1;
PointReference[] ptsArray = new PointReference[];
ptsArray[] = pt1;
ptsArray[] = pt2;
List<PointReference> ptsList = new List<PointReference>();
ptsList.Add(pt1);
ptsList.Add(pt2);
List<PointReference> pts2List = new List<PointReference>();
pts2List.AddRange(ptsArray); List<PointReference> pts3List = pts2List; Console.WriteLine("引用类型的数组,原始值:");
Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
ptsArray[].X, ptsArray[].Y, ptsArray[].X, ptsArray[].Y));
Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
ptsList[].X, ptsList[].Y, ptsList[].X, ptsList[].Y));
Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
pts2List[].X, pts2List[].Y, pts2List[].X, pts2List[].Y));
Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
pts3List[].X, pts3List[].Y, pts3List[].X, pts3List[].Y));
pt2.X = ;
pt1.Y = -;
ptsArray[].X = ;
ptsArray[].Y = ;
ptsList[] = new PointReference(, );
pts2List[] = new PointReference(-, -);
Console.WriteLine("引用类型的数组,修改后:");
Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
ptsArray[].X, ptsArray[].Y, ptsArray[].X, ptsArray[].Y));
Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
ptsList[].X, ptsList[].Y, ptsList[].X, ptsList[].Y));
Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
pts2List[].X, pts2List[].Y, pts2List[].X, pts2List[].Y));
Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
pts3List[].X, pts3List[].Y, pts3List[].X, pts3List[].Y));

其中PointReference是引用类型,先看看结果:

从结果上看pt1,pt2,ptsArray是相互影响的,因为PointReference是引用类型,另外ptsList是重新申请的一个类,只是添加了两个成员,成员是pt1,pt2,修改任意一个,也会影响这个ptsList,但是如果对ptsList的成员的X,Y是只读的,不能修改,所以只能重新赋值,在重新赋值后ptsList[0]都修改成1000,,1000了,但是其他的没有受影响,因为在修改以前里面存的引用是pt1,pt2的,在重新赋值后存的引用是重新new后的地址,自然不会对其他造成影响,然后pts2List也是一样的道理,修改pts2List是不会影响ptsList,但是会影响pts3List,因为他们的集合地址的引用是一样的,公用的存储空间。

我希望从这个例子中可以帮我彻底的疏通我对值类型与引用类型在运用中遇到的难题。

一些图示我就不画了,实际去分析我上传的例子就非常清楚了。

http://files.cnblogs.com/files/monkeyZhong/ReferenceTypeVSValueTypeDemo.zip

关于C#编程中引用与值类型赋值的一些容易犯错的地方的更多相关文章

  1. C#中,为什么在值类型后面加问号

    在C#中,声明一个值类型或引用类型的变量,无论是否给这个变量赋初值,该变量都有默认值: 比如声明引用类型变量: string a,其等效于string a = null,string的默认值为null ...

  2. Asp.net MVC 中Controller返回值类型ActionResult

    [Asp.net MVC中Controller返回值类型] 在mvc中所有的controller类都必须使用"Controller"后缀来命名并且对Action也有一定的要求: 必 ...

  3. Controller 中Action 返回值类型 及其 页面跳转的用法

        •Controller 中Action 返回值类型 View – 返回  ViewResult,相当于返回一个View 页面. -------------------------------- ...

  4. Web API中的返回值类型

    WebApi中的返回值类型大致可分为四种: Void/ IHttpActionResult/ HttpResponseMessage /自定义类型 一.Void void申明方法没有返回值,执行成功后 ...

  5. C#中引用类型和值类型

    C#的值类型包括:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型. C#的引用类型包括:数组,用户定义的类.接口.委托,object,字符串. 值类型和引用类型的区别在于,值类型的变 ...

  6. C#中引用类型和值类型的区别,分别有哪些

    C#的值类型包括:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型. C#的引用类型包括:数组,用户定义的类.接口.委托,object,字符串. 数组的元素,不管是引用类型还是值类型, ...

  7. C#中 哪些是值类型 哪些是引用类型

    DateTime属于 结构类型,所以是  值类型 在 C#中 简单类型,结构类型,枚举类型是值类型:其余的:接口,类,字符串,数组,委托都是引用类型

  8. 在JavaScript中引用类型和值类型的区别

    一.存储方式不一样 基本数据类型 变量存储的是简单的数据段,存储的是具体的值,是轻量级的数据存储方式 引用类型 引用类型的值,可以由多个值构成的对象,引用类型的变量存储的是对象引用地址.引用类型是重量 ...

  9. MVC 中Controller返回值类型ActionResult

    下面列举Asp.net MVC中Controller中的ActionResult返回类型 1.返回ViewResult视图结果,将视图呈现给网页 public ActionResult About() ...

随机推荐

  1. LA 3998 Prime k-tuple

    题意:如果K个相邻素数p1,p2,p3.....pk满足pk-p1=s,称这些素数组成一个距离为s的素数K元组,输入a,b,k,s,输出区间[a,b]内距离为s的素数k元组的个数. 思路:先打到500 ...

  2. 深入浅出 Java Concurrency (2): 原子操作 part 1

    转:http://www.blogjava.net/xylz/archive/2010/07/01/324988.html 从相对简单的Atomic入手(java.util.concurrent是基于 ...

  3. 使用spring-amqp结合使用rabbitmq

    maven 依赖包配置如下: <dependencies> <dependency> <groupId>org.springframework.amqp</g ...

  4. Unity NGUI实现按钮点击播放Aniamtion

    unity版本:4.5 NGUI版本:3.6.5 参考链接:http://www.colabug.com/thread-1029974-1-1.html,作者:COLABUG.COM 橘虞 1.怎么创 ...

  5. 怒刷BZOJ记录(一)1001~1037

    我实在是太弱了...不滚粗只能刷BZOJ了...这里来记录每天刷了什么题吧. 2015-7-9 : 1001[BeiJing2006]狼抓兔子                 | 最大流练习(呃..其 ...

  6. python编译环境发掘——从IDLE到sublime到pycharm到Anaconda

    一个好的编译器对于我们处理日常的科研很关键,好的编译器无论是从界面,字体风格,提示,调试等各方面都能从用户角度出发,提供最好的使用体验.Python本身自带的IDLE或者在CMD里进行操作和调试,对于 ...

  7. poj1065

    题目大意: 木棍(好吧,承认确实做过这个题,嘎嘎) 有一堆木棍大约有n根,木棍的长度和重量都预先知道,这些木棍会在一个木工机械上一个接一个的处理,这需要一些时间,称为设置时间,为机械准备处理一根木头, ...

  8. 那些年我用awk时踩过的坑——awk使用注意事项

    由于项目经历原因,经常使用awk处理一些文本数据.甚至,我特意下载了一个windows上的awk:gawk.exe,这样在windows上也能享受awk处理数据的方便性,. 俗话说,"常在河 ...

  9. Java中实例方法,实例变量,静态方法,静态变量,final方法重写的问题,覆盖

    Java中只有非私有的实例方法能被重写,即实现多态,子类可以覆盖父类的方法,但是实例变量不能覆盖,若子类和父类均定义了同样名称的变量,则对于子类来说这是两个不同的变量,要想调用父类的变量必须显示去调用 ...

  10. ArrayList、LinkedList、HashMap底层实现

    ArrayList 底层的实现就是一个数组(固定大小),当数组长度不够用的时候就会重新开辟一个新的数组,然后将原来的数据拷贝到新的数组内. LinkedList 底层是一个链表,是由java实现的一个 ...