IDisposable的另类用法

目录

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

1
2
3
4
5
6
7
8
public void ReadFile()
{
    using (var reader=new StreamReader("c:\\test.txt"))
    {
       var text= reader.ReadToEnd();
        Console.WriteLine(text);
    }
}

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

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

1
2
3
4
5
6
7
8
9
10
11
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class DisposableAction:IDisposable
{
    private readonly Action _action;
 
    public DisposableAction(Action action)
    {
        _action = action;
    }
 
    public void Dispose()
    {
        _action();
    }
}

进一步实现之前的需求

1
2
3
4
5
6
7
8
9
10
11
12
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来实现,而该文并没有给出如何取消订阅的方法。利用本文的内容将会实现一个优雅的取消订阅方案:

1
2
3
4
5
6
public IDisposable OnAlarm(Action<AlarmData> alarmAction)
 {
     _alarmActions.Add(alarmAction);
 
     return new DisposedAction(()=>_alarmActions.Remove(alarmAction));
 }

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

1
2
3
4
using (_clock.OnAlarm(data => {/*alarm*/ }))
           {
                
           }

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

posted @   richiezhang  阅读(1363)  评论(2编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示