关于C#中readonly的一点小研究
可能园子里有不少文章已经说明了这个问题了,但是我在这里写这篇博客只是写写自己的一些体会,也权当是整理归纳,高手莫见笑。
===============正文分割线==================
现在正在学《编译原理》课,老师让我们根据给出的语言定义自己开发一个编译器,本人对C#还是比较熟悉的所以优先选择C#作为开发工具。本人用的是VS2012配Resharper,这是一个很好用的代码分析及重构的工具,简化了不少工作,但也有些问题一直都搞不懂。例如,在这个类中,Resharper一直提示“将字段设为readonly”。
从字面上看,readonly即“只读”的,这就造成了误解,让我误以为readonly的变量是不可编辑的,因此一直没敢用这条建议。
但是既然这么提示了,总应该是有道理的。因此我就查了很多资料,包括在园子里提问,在加上自己的一点研究,终于算是搞懂了意思。
例如我们这里有一个类
class TestClass2
{
private int someValue; public void ChangeValue(int newValue)
{
someValue = newValue;
} public int ShowValue()
{
return someValue;
}
}
而在另一个类中使用它
class TestClass
{
private readonly TestClass2 tc; // 注意此处tc是readonly的 public TestClass()
{
tc = new TestClass2();
} public void ChangeTCValue(int value)
{
tc.ChangeValue(value);
} public void Show()
{
Console.WriteLine("{0}", tc.ShowValue());
}
}
我们看到虽然tc这个字段是readonly的,但是可以使用方法来改变tc中someValue的值。似乎这个“只读”失去了意义,因为可以修改它的值的话还叫什么“只读”呢?
非也!
从上面的代码中我们可以看到,tc的类型是TestClass2,是一个引用类型。而引用类型是必须用new关键字为它分配了一块内存以后它才能在后续代码中工作的。也就是说,tc这个变量仅仅是一块内存地址罢了。图示如下:
也就是说,这里的“readonly” tc只是无法再重新更改它的引用,但它所引用对象的属性是可以改变的。
那么为什么不用const呢?还是因为tc是引用,是动态分配内存的,不可能在编译阶段就确定它的地址,这点和值类型(包括string)是完全不一样的。
综上所述,可以得出结论:readonly修饰的字段,其初始化仅是固定了其引用(地址不能修改),但它引用的对象的属性是可以更改的。
当然,这里的“地址不能修改”指的是在代码中不能再对readonly变量进行再赋值,实际运行情况中可能会遇到GC或反射改变内存的情况。但是在本文所说的环境下不必考虑。(2013-9-27 14:30修改)
所以,大胆放心的用readonly吧,这样还可以防止不必要的再赋值,保证了这个对象的安全性。
PS:这样的两个类之间的关系事实上就是UML中的组合关系
关于C#中readonly的一点小研究的更多相关文章
- VB.NET开发中遇到的一点小问题
在用vb.net开发的security support时,遇到一个问题,在trainingCourses.aspx页面上增加了一个HyperLink控件 <asp:HyperLink runat ...
- 关于 const 的一点小研究
在饱受 var 的折磨之后,ES6 终于推出了新的定义变量的方法:let 和 const 和 var 相比,let 和 const 有了自己的作用域,let 用于定义变量,而 const 用于定义常量 ...
- js中全局变量的一点小知识点
js中有三种方式定义全局变量: 在任何函数外面直接执行var语句,例如:var f="value"; 直接添加一个属性到全局变量上,在web浏览器中,全局对象名为window.例如 ...
- 关于FireMonkey TGrid赋值的一点小研究
FireMoneky的TStringGrid用法和VCL里面的差不多, 但是另一个TGrid实在是奇葩, 几乎找不到给单元格赋值的方法(除了使用LiveBind) 看了其源码, 发现只要给某个Colu ...
- 使用yii中CSecurityManager的一点小技巧
当我们使用CSecurityManager::encrypt对字符串进行加密, 加密后的字符串是一串乱码(看起来确实像乱码, 具体是什么有待考证), 这不利于我们的下一步操作. 我们可以使用base6 ...
- 关于C#中readonly
关于C#中readonly的一点小研究 关于C#中readonly的一点小研究 可能园子里有不少文章已经说明了这个问题了,但是我在这里写这篇博客只是写写自己的一些体会,也权当是整理归纳,高手莫见笑 ...
- BUI Webapp用于项目中的一点小心得
接触BUI也有一段时间,也用在了移动端的项目开发中,总的来说,该框架用起来也挺灵活的,控件可以自由定制,前提是自己能认真地学习该框架的api,因为api里面说的东西比较详细,如果没有仔细看的,可能有些 ...
- net core体系-web应用程序-4net core2.0大白话带你入门-8asp.net core 内置DI容器(DependencyInjection,控制翻转)的一点小理解
asp.net core 内置DI容器的一点小理解 DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IO ...
- 记录Python学习中的几个小问题
记录Python学习中的几个小问题,和C#\JAVA的习惯都不太一样. 1.Django模板中比较两个值是否相等 错误的做法 <option value="{{group.id}}&q ...
随机推荐
- Shou 团队诚意满满的招募 Swifter
一.团队介绍 团队产品 VPlayer 播放器靠自增长 3 年内获得全球 4000 万用户,开发的 Vitamio 组件更是获得微博.UC.金山等知名企业授权使用.—— 团队再次起航,经历一年多我们已 ...
- 常用API——日期型函数Date
上图 ·声明 var myDate = new Date(); //系统当前时间 var myDate = new Date(yyyy, mm, dd, hh, mm, ss); var myDate ...
- 全新的membership框架Asp.net Identity(1)——.Net membership的历史
在Asp.net上,微软的membershop框架经历了Asp.net membership到Asp.net simple membership,再到现在的Asp.net Identity. 每一次改 ...
- Python简单爬虫入门二
接着上一次爬虫我们继续研究BeautifulSoup Python简单爬虫入门一 上一次我们爬虫我们已经成功的爬下了网页的源代码,那么这一次我们将继续来写怎么抓去具体想要的元素 首先回顾以下我们Bea ...
- Mysql慢查询和慢查询日志分析
Mysql慢查询和慢查询日志分析 众所周知,大访问量的情况下,可添加节点或改变架构可有效的缓解数据库压力,不过一切的原点,都是从单台mysql开始的.下面总结一些使用过或者研究过的经验,从配置以 ...
- 有关stm32的问题,程序里面的u8、u16这些是什么意思啊
u8 是 unsigned charu16 是 unsigned shortu32 是 unsigned int
- Ubuntu nginx 配置404错误页面
1.创建自己的404.html页面: 2.更改nginx.conf在http定义区域加入: /etc/nginx# vim nginx.conf 下添加 fastcgi_intercept_error ...
- SVN 提交失败: permission denied - txn-current-lock
执行以下命令即可 sudo chown -R www-data:subversion myproject sudo chmod -R g+rws myproject
- hortonworks2.5.3 install step log
1.创建本地YUM源,下载TAR.GZ HDP,HDP-UTILS,AMBARI介质安装HTTPD,在/VAR/WWW/HTML/下创建三个相应的目录,把以上解压的三个目录链接过来在三个目录中执行命令 ...
- .Net 扩展方法集合.
在项目中很多时候都会对字符串和集合做特定的处理.而且很多地方都会去调用.为了解决这些问题.我们通常会在项目中吧这些方法提成公共方法.下面是自己总结的项目中用到的一些扩展方法.封装成了一个Libra ...