IDisposable的另类用法

IDisposable是.Net中一个很重要的接口,一般用来释放非托管资源,我们知道在使用了IDisposable的对象之后一定要调用IDisposable.Dispose()方法,或者使用.Net提供的关键字using来达到这一目的,如:

        public void ReadFile()
        {
            using (var reader=new StreamReader("c:\\test.txt"))
            {
               var text= reader.ReadToEnd();
                Console.WriteLine(text);
            }
        }

使用using关键字后,编译器将在他的末尾自动插入一个Dispose方法的调用。我们可以利用这一点尝试完成下面的需求:

我们希望将警告的文本以红色显示在控制台上,然后再恢复初始颜色显示其他文本内容。按照传统做法,我们先存储初始颜色,设定新颜色,向控制台输出警告信息,恢复初始颜色,输出其他文本。

        public void Show()
        {
            var originalColor = Console.ForegroundColor;

            Console.ForegroundColor = ConsoleColor.Red;

            Console.WriteLine("dangerous message");

            Console.ForegroundColor = originalColor;
            Console.WriteLine("other message");
        }

如果利用我们前面分析的IDisposable模式,我们先实现一个能够接收Action类型的通用Disposable:

    public class DisposableAction:IDisposable
    {
        private readonly Action _action;

        public DisposableAction(Action action)
        {
            _action = action;
        }

        public void Dispose()
        {
            _action();
        }
    }

进一步实现之前的需求

       public void Show()
        {
            var originalColor = Console.ForegroundColor;

            using (new DisposableAction(()=>Console.ForegroundColor=originalColor))
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("dangerous message");
            }

            Console.WriteLine("other message");
        }

这似乎也没比上面高明多少,是因为这个例子不能够展现这个模式的威力。在《三种观察者模式的C#实现》一文中,我介绍的第三种方案是利用Action来实现,而该文并没有给出如何取消订阅的方法。利用本文的内容将会实现一个优雅的取消订阅方案:

       public IDisposable OnAlarm(Action<AlarmData> alarmAction)
        {
            _alarmActions.Add(alarmAction);

            return new DisposedAction(()=>_alarmActions.Remove(alarmAction));
        }

如果想只订阅一次,就使用using:

 using (_clock.OnAlarm(data => {/*alarm*/ }))
            {

            }

反之,如果不想取消订阅就不要使用using,不要调用Dispose()方法。

时间: 2024-10-12 14:15:33

IDisposable的另类用法的相关文章

PHP return语句另类用法

分享下PHP return语句的另一个作用,在bbPress的代码中看到的一个奇葩使用方法. 一直以为,return只能出现在函数中,直到看了bbPress的代码: <?php require_once('./bb-load.php'); bb_repermalink(); // The magic happens here. if ( $self ) { if ( strpos($self, '.php') !== false ) { require($self); } else { requ

写在Github被微软收购之际 - Github的那些另类用法

这几天朋友圈被微软75亿美元收购Github的新闻刷屏了.Jerry也来贡献一篇和Github相关的文章. 这篇文章包含了Jerry平时对于Github的一些另类用法.目录如下: 1. 部署HTML应用到Github并运行 2. Github和云平台的集成 3. ABAP Git客户端 4. 用Github搭建个人博客 5. 一些提高工作效率的小窍门 6. Github周边 如果您也有使用Github的小技巧,欢迎留言. 1. 部署HTML应用到Github并运行 这个技巧其实是把Github作

滴答清单子作务另类用法

滴答清单子作务另类用法 滴答清单有一个子任务功能. 一个主任务里可以包含很多个子任务. 我目前有一个另类用法就是流程处理. 比如我要采购一个东西,我可以建立一个主任务,然后在子任务中加入这个任务的第一个步骤. 这样可以先计划好,之后跟着一步一步完成. 有人说计划赶不上变化,但是在我看来有计划可以更靠近目标,而没有计划只能靠碰运气了. 原文地址:https://www.cnblogs.com/F4NNIU/p/9279700.html

Python装饰器的另类用法

之前有比较系统介绍过Python的装饰器,本文算是一个补充.今天我们一起探讨一下装饰器的另类用法. 语法回顾 开始之前我们再将Python装饰器的语法回顾一下. @decorate def f(...): pass 等同于: def f(...): pass f = decorate(f) @语法的好处在于: 相同的函数名只出现一次,避免了f = decorate(f)这样的语句. 可读性更高,让读代码的人一眼就明白函数被装饰了哪些功能. @call()装饰器 假设你要创建一个整数平方的列表,你

CSS ::before 和 ::after 伪元素另类用法

原文地址:http://justcoding.iteye.com/blog/2032627 CSS 有两个说不上常用的伪类 :before 和 :after,偶尔会被人用来添加些自定义格式什么的,但是它们的功用不仅于此.前几天发现了 Creative Link Effects 这个非常有意思的介绍创意链接特效的页面,里面惊人的效果大量使用到的特性除了 transform 属性进行变形之外,就是接下来要介绍的这两个伪元素了. 一 基本语法 在了解进阶的应用之前,先来了解一下语法规则.平常仅仅需要将

渗透中Necat的另类用法

Necat 是一个伟大而实用的用于 TCP 和 UPD 网络连接协议的读写程序.同时 Necat 也被誉为网络中的瑞士军刀,在许多黑客教程中 Necat 也被广泛使用.Necat 最常见用途是设置反向连接和 bind shell ,管道和重定向网络流量,端口侦听,调试程序和脚本,抓取 banner 等作用.在本教程中,我们将学到以下内容: 1. Banner 抓取 2. 原始连接 3. Webserver 交互 4. 文件传输 5. Necat 端口扫描6. 绑定和反弹 shell 我们将使用运

【旧代码整理】Nodejs的另类用法

Nodejs 的中文维基百科介绍:https://zh.wikipedia.org/wiki/Node.js Nodejs 可以 在linux命令行执行js代码. 比如: var a = 1; var b = 2; var c = a + b; console.log(c+"\r"); 以上代码保存为 test.js 然后执行命令: [email protected]:~/# nodejs test.js 3 再看下面,用nodejs执行新浪微博登录加密密码的js:(这堆代码是别人整理

字符串驻留池的另类用法

起因 事情的起因是这样的 基于某些无法避免的因素 我有2个dll 暂且叫 a.dll 和 b.dll 这2个类库中有一部分完全相同的代码(下文中称为代码C)——遍历当前应用程序下的所有类库文件,并注入插件(没错,就是IOC了) 当开发人员仅引用a.dll或仅b.dll的时候,并没有任何问题 但是如果一个项目需要同时引用 a.dll 和 b.dll 那么麻烦就来了 那部分完全相同的代码会被执行2次, 所有插件都会被加载2次 经过 最简单的方案当然是把a.dll和b.dll中相同的代码 抽出成c.d

ls另类用法

通常ls列出的文件,想直接管道通过rm -rf删除是无效的.这时就要配合命令xargs使用了: 例如: ls -t|tail -10|xargs rm -rf    //按时间排序,删除最后的10个文件 ls -lt|tail -100|awk '{ print $9 }'|xargs rm -rf 两者效果是相同的同理,如果想按时间倒序排列,也就是说离现在最近的时间越排在最后显示,就用ls -rt当然,也可以使用find 配合rm删除.