zoukankan      html  css  js  c++  java
  • 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()方法。

  • 相关阅读:
    fn project 试用之后的几个问题的解答
    fn project 扩展
    fn project 生产环境使用
    fn project 对象模型
    fn project AWS Lambda 格式 functions
    fn project 打包Function
    fn project Function files 说明
    fn project hot functions 说明
    fn project k8s 集成
    fn project 私有镜像发布
  • 原文地址:https://www.cnblogs.com/richieyang/p/5154985.html
Copyright © 2011-2022 走看看