RAII
· 3 min read
本文总结了不同语言实现 RAII 的方式。
构造器-析构器
- C++
- Rust
#include <cstdio>
struct Locker {
Locker() {
puts("lock");
}
~Locker() {
puts("unlock");
}
};
int main() {
Locker locker;
}
struct Locker {}
impl Locker {
pub fn new() -> Self {
println!("lock");
Locker {}
}
}
impl Drop for Locker {
fn drop(&mut self) {
println!("unlock")
}
}
pub fn main() {
let locker = Locker::new();
}
控制块
- Java
- C#
- Python
class Locker implements AutoCloseable {
public Locker() {
System.out.println("lock");
}
@Override
public void close() {
System.out.println("unlock");
}
public static void main(String[] args) {
try (Locker locker = new Locker()) {
}
}
}
using System;
class Locker : IDisposable
{
public Locker()
{
Console.WriteLine("lock");
}
public void Dispose()
{
Console.WriteLine("unlock");
}
static void Main(string[] args)
{
using var locker = new Locker();
}
}
class Locker:
def __enter__(self):
print("lock")
def __exit__(self, *args):
print("unlock")
with Locker():
pass
defer 语句
- Go
- Swift
import "fmt"
func main() {
defer fmt.Println("unlock")
fmt.Println("lock")
}
defer {
print("unlock")
}
print("lock")
思考题
这样写实现 RAII 有什么问题:
- Java
- C#
- Python
var r1 = open("r1");
var r2 = open("r2");
try {
// ...
} finally {
r1.close();
r2.close();
}
var r1 = open("r1");
var r2 = open("r2");
try {
// ...
} finally {
r1.close();
r2.close();
}
r1 = open("r1")
r2 = open("r2")
try:
# ...
finally:
r1.close()
r2.close()
正确的写法应该是:
- Java
- C#
- Python
try (var r1 = open("r1"); var r2 = open("r2")) {
// ...
}
using var r1 = open("r1");
using var r2 = open("r2");
// ...
with open("r1") as r1, open("r2") as r2:
# ...
这种写法语前面的写法不同,而是等价于下面的写法:
- Java
- C#
- Python
var r1 = open("r1");
try {
var r2 = open("r2");
try {
// ...
} finally {
r2.close();
}
} finally {
r1.close();
}
var r1 = open("r1");
try {
var r2 = open("r2");
try {
// ...
} finally {
r2.close();
}
} finally {
r1.close();
}
r1 = open("r1")
try:
r2 = open("r2")
try:
# ...
finally:
r2.close()
finally:
r1.close()
因此这个语法糖相当于是把嵌套结构变成并列结构了,大大简化了代码编写。