【翻译】C# Tips & Tricks: Weak References - When and How to Use Them
原文:C# Tips & Tricks: Weak References - When and How to Use Them
Sometimes you have an object which is very large and needed multiple times, but not constantly, throughout your application. For example a huge lookup table, or the contents of a large file you need in memory for some algorithm. To work with this object, you traditionally have two options:
- As a local variable inside the method that needs it
- As a field in a class that lives during the whole time the object could be needed
有时候,你有一个很大的对象,多次但又不经常需要它,且遍布整个应用。比如一个庞大的查找表或者一个大文件的内容存于内存中用于一些算法。传统地,要使用这个对象,你有两种选择:
- 作为一个局部变量内置于需要它的方法中
- 作为一个字段存在于一个类中,存活于需要该对象的整个时间周期中
Both solutions aren't optimal if your object is very huge, and only sometimes needed:
如果你的对象十分大,并且只有有些时候需要,那么以上两种方法都不是最理想的:
The class field solution keeps the object in memory the whole time, giving your application a huge permanent memory footprint increase. And the local variable solution will decrease application performance, since the object not only has to be created anew every time it's needed, but also deleted each time it goes out of scope, generating work for the Garbage Collector.
类字段的方案整个时间周期保持对象于内存中,造成内存持久占用。局部变量方案会降低应用的性能,因为不仅要在每次需要它的时候被重新创建,而且在每次超出作用域的时候删除它,给垃圾回收增加了工作量。
If the creation of the object is very expensive, and you want to avoid doing it multiple times, the class field solution is your way to go. But in all cases where the object is a cheap-to-create memory hog, a better solution than both of the above would be welcome.
如果创建这个对象代价非常高,你想避免多次这样操作,类字段的方法是你会采用的。但是当这个对象可以被廉价创建,一种较之于以上两种方案更好的方案将会更受欢迎。
Luckily for us, .Net 4.0 gives us a middle-ground solution in the form of weak references.
幸运的是,.Net 4.0以弱引用的形式给了我们一个折衷的方案。
Usually, when an object goes out of scope, or is set to null, it is no longer accessible to us, even if the garbage collector will only delete the object much later.
通常,当一个对象超出作用域或者被置空,对于我们它将不再能被访问,尽管垃圾回收会在很久以后删除这个对象。
A weak reference object will keep a reference to an object that went out of scope or was set to null, until it is actually deleted by the garbage collector. But until that happens, we can get the object back!
一个弱引用对象将会保持一个指向一个超出作用域或者被置空的对象的引用,直到它确实被垃圾回收删除。直到被删除前,我们一直可以把该对象取回来。
So our new option to work with a large object is to use a weak reference to it. The weak reference itself should become a long-living class member. And in the method that needs our huge object, we check if the weak reference holds an object, which we will use if it does. And if not, we create a new instance.
于是我们对于一个较大对象的选择是使用一个弱引用指向它。这个弱引用本身将成为一个长期存活的类成员。在需要我们的大对象的方法中,我们检查这个弱引用是否持有一个对象,如果是则我们将会使用它。如果不是,我们创建一个新实例。
This way, when we first run our method, a new instance of the huge object is created. But when we run it the next time, and the garbage collector hasn't deleted the object in the meantime, we can reuse it, and don't need to create a new instance.
这样,当我们第一次运行我们的方法的时候,这个大对象的一个新实例会被创建。但当我们下次运行它时,与此同时垃圾回收还没有删除找个对象,我们可以重用它,而不需要创建一个新的实例。
The actual usage is pretty simple.
实际用法很简单。
To create a weak reference to an object, we simply call the constructor with the object:
为了创建一个指向一个对象的弱引用,我们简单的的调用这个构造器并传入这个对象:
WeakReference w = new WeakReference(MyHugeObject);
To get the underlying object from a weak reference, we use its .Target property:
为了从一个弱引用中得到这个对象,我们使用 its.Target 属性:
MyHugeObject = w.Target as MyHugeClass;
If the object still exists, it is returned. If it was claimed by the garbage collector, a null refence is returned by the 'as' operator.
如果这个对象一直存在,他会被返回。如果被垃圾回收了,会通过 'as' 操作符返回一个空引用。
So, given that we have a WeakReference w as a field in our class, we would use it inside the method that does something with a HugeObject like this:
于是,在我们的类中有一个 WeakReference 类型的变量 w 作为一个字段,我们将在这个方法里使用它结合一个 HugeObject 来做一些事情,像这样:
static void Func()
{
MyHugeClass MyHugeObject;
if ( (w == null) || ( (MyHugeObject=w.Target as MyHugeClass) == null) )
{
MyHugeObject = new MyHugeClass();
w = new WeakReference(MyHugeObject);
}
// work with MyHugeObject
}
First we declare the MyHugeObject variable, which will be initialized to null by the compiler. Then we check if our weak refence is null (which is the case when Func runs for the very first time) or if the assignment from w.Target returned null. If either is the case, we (re)create MyHugeObject and assign it to w, after which we can then do some work with MyHugeObject.
首先我们声明了这个 MyHugeObject 类型的变量,将会被编译器初始化为 null 。然后我们检查我们的弱引用是否为空(就是在 Func 第一次运行的情况)或者 w.Target 为空。如果满足任何一种情况,我们创建 MyHugeObject 并把它赋值给 w,之后,我们可以用 MyHugeObject 来做些事情。
Now, WeakReference does us one huge favor: it takes care of all members of MyHugeObject, and makes sure we only get it back if all its members are still intact, so we don't need to worry that we get back an incomplete object.
现在,WeakReference 带给我们一个好处:它负责 MyHugeObject 的所有成员,并确保只有在它所有成员完整无缺的情况下我们才能取回它,因此我们不需要担心取回一个不完整的对象。
A drawback is that WeakReference doesn't play well with objects that implement IDisposable, since we cannot call Dispose() (or have it called automatically through the 'using' statement) through a WeakRefence to the object.
WeakReference 的一个缺点是不能很好地和实现 IDisposable 接口的对象协作,是因为我们不能通过一个指向该对象的 WeakRefence 来调用 Dispose()(或者通过 'using' 语句自动使它被调用)。
And finally a word of warning: weak references aren't a guaranteed profit for application performance. In most cases, they will make an algorithm more performant than when using very large local variables. But it's not guaranteed, and in some cases it could produce noticeable overhead (for example when the huge object is a data structure consisting of many smaller objects with references to each other, and a WeakRefence to the data structure turns all those internal refernces to weak references, this might incur garbage collector overhead, because every reference has to be checked to decide if the object as a whole can be recovered or deleted).
最后一个警告:弱引用不能保证为应用的性能带来好处。在大多数情况下,它们会使算法更高性能的,较之于使用一个大局部变量。但这并不能被保证,且在有些情况下会引起明显的开销(比如,当这个大对象是一个由许多较小的之间互相引用的对象构成的数据结构,一个 WeakRefence 指向这个数据结构会把所有的内部引用转变成弱引用,这可能会引起垃圾回收器的开销,因为每一个引用必须被检查来确定是否这个对象可以被恢复或者被删除)。
So the best advice with weak references is: profile or benchmark it, to make sure that you choose the best solution for your specific situation.
所以,对于弱引用的最好的建议是:概要描述或者用基准问题测试它,以确保你为特定的环境选择最好的方案。
【翻译】C# Tips & Tricks: Weak References - When and How to Use Them的更多相关文章
- [翻译]Understanding Weak References(理解弱引用)
原文 Understanding Weak References Posted by enicholas on May 4, 2006 at 5:06 PM PDT 译文 我面试的这几个人怎么这么渣啊 ...
- Must Know Tips/Tricks in Deep Neural Networks
Must Know Tips/Tricks in Deep Neural Networks (by Xiu-Shen Wei) Deep Neural Networks, especially C ...
- 45 Useful JavaScript Tips, Tricks and Best Practices(有用的JavaScript技巧,技巧和最佳实践)
As you know, JavaScript is the number one programming language in the world, the language of the web ...
- 转:45 Useful JavaScript Tips, Tricks and Best Practices
原文来自于:http://flippinawesome.org/2013/12/23/45-useful-javascript-tips-tricks-and-best-practices/ 1 – ...
- Productivity tips, tricks and hacks for academics (2015 edition)
Productivity tips, tricks and hacks for academics (2015 edition) Contents Jump to: My philosophy: Op ...
- Understanding Weak References
Understanding Weak References Posted by enicholas on May 4, 2006 at 5:06 PM PDT Some time ago I was ...
- [转]Understanding Weak References
原文地址:https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html 推荐另一篇文章:http://www ...
- 45 Useful JavaScript Tips, Tricks and Best Practices
<45 Useful JavaScript Tips, Tricks and Best Practices> http://flippinawesome.org/2013/12/23/45 ...
- Weak References
http://docwiki.embarcadero.com/RADStudio/Seattle/en/Automatic_Reference_Counting_in_Delphi_Mobile_Co ...
随机推荐
- Windows7给C盘扩容
// 在之前的系统中都是使用PartitionMagic来进行磁盘容量的分配,但PartitionMagic在Windows7中的兼容性不是好很好,导致不能使用.其实Windows7自带了磁盘管理工具 ...
- solr详解,开发必备
1.基础知识 创建索引的过程如下: (1).建立索引器IndexWriter,这相当于一本书的框架 (2).建立文档对象Document,这相当于一篇文章 (3).建立信息字段对象Field,这相当于 ...
- Solr5之Schema.xml详解
schema.xml 是用来定义索引数据中的域的,包括域名称,域类型,域是否索引,是否分词,是否存储,是否标准化即 Norms ,是否存储项向量等等. schema.xml 配置文件的根元素就是 sc ...
- 无线局域网络 WIFI/WAPI/WLAN区别浅析
WIFI和WAPI的区别 既然WIFI和WAPI都是WLAN的传输协议,那么两者究竟都有怎样的区别? 首先第一点区别在于,两者的缔造者不一样.WIFI是又国外制定的一个协议,而WAPI是由中国制定的, ...
- Android 初始化Setup Wizard——Provision
今天说说Provision这个APK,可能很多朋友都不知道有这个APK存在.Provision的作用很简单,就是一个系统初始化引导程序,原生的Android里面Provision只做了一件事,就是写入 ...
- Codeforces Round #382 (Div. 2)C. Tennis Championship 动态规划
C. Tennis Championship 题目链接 http://codeforces.com/contest/735/problem/C 题面 Famous Brazil city Rio de ...
- Android 在xml中配置 float 和 integer 值
一.float的配置方法 andriod 默认不支持float型的设置,在values 下的新建floats.xml 文件,在内部添加如下代码: <resources> <item ...
- EventBus 3.0使用
在没用eventBus之前一直用Android广播方式通知消息更新UI 广播写法 首先发送广播通知 Intent intent = new Intent(); intent.setAction(&qu ...
- IOS开发 应用程序图标数字角标
其实实现这个功能很简单,只要调用UIApplication即可. 用法用例:[UIApplication sharedApplication].applicationIconBadgeNumber ...
- C# WinForm 技巧八:界面开发之“WeifenLuo.WinFormsUI.Docking+OutLookBar” 使用
概述 最近几天一直在关注WinFrom方面的文章主要还是园子里伍华聪的博客,在看看我们自己写的项目差不忍赌啊,有想着提炼一下项目的公共部分,公共部分有分为 界面,类库两方面,今天主要是把界面 ...