C#,有没有像golang一样的'Defer Call'?
C#, is there 'Defer Call' like golang?
golang 支持 'Defer Call' 当 c++ 时,我使用这个技巧(?)。
struct DeferCall
{
DeferCall() {}
~DeferCall() { doSomeThing(); }
}
void SomeMethod()
{
DeferCall deferCall;
...
}
如何在 C# 中执行此操作?
我需要这样的golang defer tutorial
我从 here
中获取了 GoLang
中 Defer Call
的以下定义
延迟语句将函数调用推送到列表中。已保存调用列表在周围函数 returns 之后执行。 Defer 通常用于简化执行各种清理操作的函数。
C#版本:
选项 1:
- 使用
Task
API
- 将您的
DeferCall
方法包装在 Task
中
- 在正确的时间执行手动使用
Start()
方法或对于要继续的函数 post,将其包装在另一个任务对象中并使用 ContinueWith
[= 执行50=],这将链接任务一个接一个地执行
选项 2:
- 可以使整个调用链
Async-Await
,其中所有post await
关键字都在主调用完成时执行,这是标准的异步实现
最接近的等效语言是 try
-finally
:
try
{
DoSomething();
}
finally
{
DoCleanup();
}
最接近的等效框架是 IDisposable
+ using
:
using (var stream = File.OpenRead("foo.txt"))
{
// do something
}
就我个人而言,defer
术语让我感到困惑,因为 这不是 "deferred execution"(现在安排 - 稍后执行,可以通过任务实现),
但是某种 RAII 实现。
P.S。
假设您将继续学习 golang:
不,但并非不可能
defer
是一个关键字,旨在在其父函数 returns 时执行函数,并在到达 return 语句时开始执行。
由于 defer
在 go 中像堆栈一样工作,因此按顺序调用延迟函数会导致相反的顺序。
package main
import (
"fmt"
)
func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
if num := 2; num == 2 {
defer fmt.Println("4")
return
}
defer fmt.Println("5")
}
// 4
// 3
// 2
// 1
https://play.golang.org/p/jzHG-paytBG
最好的用例是关闭文件读取器、数据库事务和堆叠日志,其中需要在 returning 之前关闭。
var count
defer println(count)
for { // forever
count++
if count == 100 {
return
}
}
defer pkg.DoCleanup()
something := pkg.DoSomething()
pkg.Add(something.ForCleanup)
pkg.Add(something.ForCleanup)
stream, _ := file.OpenRead("text.txt")
defer stream.Close()
// stream closed
// pkg cleaned
// 100
解决方法就像丹尼斯的回答:
您可以使用 System.Reactive.Disposables.Disposable
来实现
void Function()
{
string fileName = "InputFile.txt";
using var defer = Disposable.Create(() => { File.Delete(fileName); });
WriteFile(fileName);
ConvertFile(fileName, "OutputFile.txt");
}
golang 支持 'Defer Call' 当 c++ 时,我使用这个技巧(?)。
struct DeferCall
{
DeferCall() {}
~DeferCall() { doSomeThing(); }
}
void SomeMethod()
{
DeferCall deferCall;
...
}
如何在 C# 中执行此操作?
我需要这样的golang defer tutorial
我从 here
中获取了GoLang
中 Defer Call
的以下定义
延迟语句将函数调用推送到列表中。已保存调用列表在周围函数 returns 之后执行。 Defer 通常用于简化执行各种清理操作的函数。
C#版本:
选项 1:
- 使用
Task
API - 将您的
DeferCall
方法包装在Task
中
- 在正确的时间执行手动使用
Start()
方法或对于要继续的函数 post,将其包装在另一个任务对象中并使用ContinueWith
[= 执行50=],这将链接任务一个接一个地执行
选项 2:
- 可以使整个调用链
Async-Await
,其中所有postawait
关键字都在主调用完成时执行,这是标准的异步实现
最接近的等效语言是 try
-finally
:
try
{
DoSomething();
}
finally
{
DoCleanup();
}
最接近的等效框架是 IDisposable
+ using
:
using (var stream = File.OpenRead("foo.txt"))
{
// do something
}
就我个人而言,defer
术语让我感到困惑,因为 这不是 "deferred execution"(现在安排 - 稍后执行,可以通过任务实现),
但是某种 RAII 实现。
P.S。 假设您将继续学习 golang:
不,但并非不可能
defer
是一个关键字,旨在在其父函数 returns 时执行函数,并在到达 return 语句时开始执行。
由于 defer
在 go 中像堆栈一样工作,因此按顺序调用延迟函数会导致相反的顺序。
package main
import (
"fmt"
)
func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
if num := 2; num == 2 {
defer fmt.Println("4")
return
}
defer fmt.Println("5")
}
// 4
// 3
// 2
// 1
https://play.golang.org/p/jzHG-paytBG
最好的用例是关闭文件读取器、数据库事务和堆叠日志,其中需要在 returning 之前关闭。
var count
defer println(count)
for { // forever
count++
if count == 100 {
return
}
}
defer pkg.DoCleanup()
something := pkg.DoSomething()
pkg.Add(something.ForCleanup)
pkg.Add(something.ForCleanup)
stream, _ := file.OpenRead("text.txt")
defer stream.Close()
// stream closed
// pkg cleaned
// 100
解决方法就像丹尼斯的回答:
您可以使用 System.Reactive.Disposables.Disposable
来实现void Function()
{
string fileName = "InputFile.txt";
using var defer = Disposable.Create(() => { File.Delete(fileName); });
WriteFile(fileName);
ConvertFile(fileName, "OutputFile.txt");
}