80人参与 • 2026-05-08 • Asp.net
先看一个问题:c# 会自动清理垃圾,为什么还需要手动释放?
c# 的内存(比如你 new 出来的对象)确实由垃圾回收器(gc)自动管理,你不用管。但是程序里还有一些不属于内存的东西,比如:
这些东西,gc 不认识,也不会帮你去关。如果你不主动释放,它们会一直存在,导致:
所以,c# 给了你一个约定:如果你用了这种特殊资源,你用完必须亲自归还。
这个约定就是 idisposable。
c# 源码里面的idisposable 是一个接口,里面只有一句话:
void dispose();
任何类(比如 filestream、sqlconnection)只要实现了这个接口,就等于贴了个标签:“我占用了特殊资源,用完请调用我的 dispose() 方法归还”。
filestream fs = new filestream("a.txt", filemode.open);
// ... 使用文件
fs.dispose(); // 归还文件
但是这样写有个隐患:如果中间代码抛出异常,dispose() 可能永远不会执行,资源照样泄露。你还得写 try-finally:
filestream fs = null;
try{
fs = new filestream("a.txt", filemode.open);// 使用文件
}finally{
if (fs != null) fs.dispose();
}
太麻烦,而且容易忘。于是 c# 提供了一个语法糖using 。
如果你的类里面包含了需要释放的东西,那么你的类也应该实现 idisposable。
class logger : idisposable{
private filestream logfile; // 这个需要释放!
public logger(string path){
logfile = new filestream(path, filemode.append);
}
public void write(string msg) {
// 写日志
}
public void dispose(){
logfile?.dispose(); // 释放掉内部的资源
}
}
然后别人用你的 logger 时:
using (var logger = new logger("app.log")){
logger.write("程序启动");
}
// 自动释放文件
原则: 如果你的类里有任何 idisposable 类型的成员(比如 filestream、sqlconnection),你就应该实现 idisposable,并在 dispose() 里调用它们的 dispose()。
using 语句的作用: 出了这个大括号,自动调用 dispose(),不管有没有异常。
基本用法:
using (filestream fs = new filestream("a.txt", filemode.open)){
// 使用 fs 读文件
}
// 到这里,自动 fs.dispose()
-----------------------------------------
//而上面的using基本用法和下面这段代码实现是一样的
filestream fs = new filestream("a.txt", filemode.open);
try{
// 使用 fs
}finally{
if (fs != null) fs.dispose();
}
所以 using 的本质 = 自动 + 安全的资源归还
等价于嵌套的 try-finally,保证两个都被释放。
using (filestream input = file.openread("1.txt"))
using (filestream output = file.openwrite("2.txt"))
{
// 复制文件内容
}
// 先自动释放 output,再释放 input
using var fs = new filestream("a.txt", filemode.open);
// 使用 fs
// 方法结束时会自动 dispose()
效果: fs 的生命周期持续到方法结束,而不是大括号结束。适合那些“在整个方法里都要用,最后一起释放”的场景。
void readfile(){
using var fs = new filestream("a.txt", filemode.open);
// 在这里使用 fs
// 方法是这里结束,fs 自动释放
}
有些场景你不想在代码块结束立刻释放,比如把对象返回给调用方使用。这时就不能在方法内 using。而在创建资源的责任交给调用方,调用方负责 using。
// 不负责释放
public stream getstream(){
return new filestream("data.bin", filemode.open);
}
// 调用方:
using (var stream = getstream()){
// 调用方负责释放
}
如果你写一个类,内部只包含托管资源(例如另一个 idisposable 对象),只需要:
public class myclass : idisposable{
private sqlconnection conn;
public void dispose() => conn?.dispose();
}
这完全正确,对于大多数日常业务代码已经足够。但是,当你面对以下情况时,简单的 dispose 就不够了:
dispose 模式 其实在实际开发并不常见,这里详情就懒得写了
dispose 模式 = 一个 dispose() 方法 + 一个受保护的 dispose(bool) 虚方法 + 一个终结器(仅当有非托管资源时)。
到此这篇关于c# idisposable 和 using的使用小结的文章就介绍到这了,更多相关c# idisposable 和 using内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论