• 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()方法。

  • 相关阅读:
    java编写socket使用bufferedReader.readLine()问题研究
    stage3D基础五-----Working with 3D cameras(转)
    stage3D基础四----Stage3D和透视投影的使用(转)
    stage3D基础三------什么是AGAL(转)
    stage3D基础二-----顶点和片段着色器(转)
    stage3D基础一-----Stage3D如何工作(转)
    OpenGL/GLSL数据传递小记(3.x)(转)
    OpenGL/GLSL数据传递小记(2.x)(转)
    Away3D引擎学习笔记(二)CameraController相机控制的应用
    I-team 博客全文检索 Elasticsearch 实战
  • 原文地址:https://www.cnblogs.com/richieyang/p/5154985.html
Copyright © 2020-2023  润新知