关于C#编程中引用与值类型赋值的一些容易犯错的地方
值类型与引用类型的区别在于:值类型在赋值的时候是拷贝值,引用类型在赋值的时候的拷贝引用。记住这一个原则,我们再来分析一些具体情况:
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#编程中引用与值类型赋值的一些容易犯错的地方的更多相关文章
- C#中,为什么在值类型后面加问号
在C#中,声明一个值类型或引用类型的变量,无论是否给这个变量赋初值,该变量都有默认值: 比如声明引用类型变量: string a,其等效于string a = null,string的默认值为null ...
- Asp.net MVC 中Controller返回值类型ActionResult
[Asp.net MVC中Controller返回值类型] 在mvc中所有的controller类都必须使用"Controller"后缀来命名并且对Action也有一定的要求: 必 ...
- Controller 中Action 返回值类型 及其 页面跳转的用法
•Controller 中Action 返回值类型 View – 返回 ViewResult,相当于返回一个View 页面. -------------------------------- ...
- Web API中的返回值类型
WebApi中的返回值类型大致可分为四种: Void/ IHttpActionResult/ HttpResponseMessage /自定义类型 一.Void void申明方法没有返回值,执行成功后 ...
- C#中引用类型和值类型
C#的值类型包括:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型. C#的引用类型包括:数组,用户定义的类.接口.委托,object,字符串. 值类型和引用类型的区别在于,值类型的变 ...
- C#中引用类型和值类型的区别,分别有哪些
C#的值类型包括:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型. C#的引用类型包括:数组,用户定义的类.接口.委托,object,字符串. 数组的元素,不管是引用类型还是值类型, ...
- C#中 哪些是值类型 哪些是引用类型
DateTime属于 结构类型,所以是 值类型 在 C#中 简单类型,结构类型,枚举类型是值类型:其余的:接口,类,字符串,数组,委托都是引用类型
- 在JavaScript中引用类型和值类型的区别
一.存储方式不一样 基本数据类型 变量存储的是简单的数据段,存储的是具体的值,是轻量级的数据存储方式 引用类型 引用类型的值,可以由多个值构成的对象,引用类型的变量存储的是对象引用地址.引用类型是重量 ...
- MVC 中Controller返回值类型ActionResult
下面列举Asp.net MVC中Controller中的ActionResult返回类型 1.返回ViewResult视图结果,将视图呈现给网页 public ActionResult About() ...
随机推荐
- Strust2的json插件
以下这段摘自网上: Json是一种轻量级的数据交换格式,JSon插件提供了一种名为json的ActionResultType .一旦为Action指定了该结果处理类型,JSON插件就会自动将Actio ...
- (转载)php flush()刷新不能输出缓冲的原因分析
(转载)http://www.webkaka.com/tutorial/php/2012/110628/ 在php程序编写中,flush()的使用率还是挺高的,它在网页表现即时信息效果时发挥了极为重要 ...
- Ubuntu下安装Skyeye
ubuntu12下安装skyeye1.3.2 1.首先安装skyeye的依赖包,比如gtk的依赖,一般Ubuntu 都默认安装了,稳妥起见,运行下面的代码: sudo apt-get install ...
- poj 1149 最大流
题目链接:http://poj.org/problem?id=1149 #include <cstdio> #include <cmath> #include <algo ...
- [转]windows10 64位环境下安装mysql5.7.17
今天以zip模式在windows10 64位环境下安装mysql5.7,到最后一步提示mysql服务无法启动. 安装步骤如下: 1.配置环境变量 我的电脑->属性->高级->环境变量 ...
- AE 3D摄像机工作原理
看了AE教程的3D可视化音频和序列法导入三维模型之后对于视频解析3D是有了更深的认识.很感谢AE在CS6之后加入了3D摄像机跟踪器的功能.它是通过摄像机跟踪反求来得到影片中的平面特征点.然后由用户指定 ...
- 每个项目单独配置 git 用户
git多账号登陆问题 设置git全局设置: git config --global user.name "your_name" git config --global user. ...
- Angular2学习
1.新建项目 2.新建Model public class TodoItem { public int Id { get; set; } public string Key { get; set; } ...
- OS开发 touch事件的优先级和事件传递
界面类的对象一般都是可以接触点击事件的,只不过有的默认接受,有的需要设定属性. userInteractionEnabled 属性设置为YES的时候就可以接受点击事件了 - (void)touches ...
- POJ1184-------操作分离的BFS
题目地址:http://poj.org/problem?id=1184 题目意思: 给你两个6位数,一个是起始值,一个最终值 初始光标在最左边 你可以左移或者右移光变 在光标处+1或者-1 在光标处和 ...