C# .NET Core - 在外部声明时,一次性对象是否会在 try/catch 块中持续存在?这是不好的做法吗?

问题描述 投票:0回答:1

尝试通过 Serilog 上下文、using 语句和一些 try/catch 块来理解最佳实践。当我在一些方法中记录任何内容时,我试图在 Serilog 上下文中包含一些数据的 ID。

所有这些方法都被简单的 try/catch 块包围,我正在尝试找出插入

using
语句的最佳方法。

第一个方法对我来说是正确的,因为我知道它将在方法结束时被处置 - 但如果

try
块内出现错误,它仍然会处置我的
ctxId
对象吗?我的直觉告诉我不行,但我似乎找不到答案。

[Route("method")]
public async Task<IActionResult> Method(Parameters params) { 
  using var ctxId = Serilog.Context.LogContext.PushProperty("Id", params.Id.ToString());
  try { 
    // do stuff
    _logger.LogInformation("info...");
  }
  catch (Exception ex) {
    _logger.LogError("error...", ex); 
  }
}

理想情况下,我不想做这样的事情(如下)并重复这些行。

[Route("method")]
public async Task<IActionResult> Method(Parameters params) { 
  try { 
    // do stuff
    using var ctxId = Serilog.Context.LogContext.PushProperty("Id", params.Id.ToString());
    _logger.LogInformation("info...");
  }
  catch (Exception ex) {
    using var ctxId = Serilog.Context.LogContext.PushProperty("Id", params.Id.ToString());
    _logger.LogError("error...", ex); 
  }
}

c# try-catch serilog using idisposable
1个回答
2
投票

但是如果 try 块内出现错误,它仍然会处置我的 ctxId 对象吗?

是的。

using
仍然只是 try/finally 的“语法糖”。所以你的方法被重写为:

ContextId ctxId = null;
try{
  ctxId = Serilog.Context.LogContext.PushProperty("Id", params.Id.ToString());
  try { 
    // do stuff
    _logger.LogInformation("info...");
  }
  catch (Exception ex) {
    _logger.LogError("error...", ex); 
  }
}
finally{
    ctxId?.Dispose();
}

无论

//do stuff
中发生什么*,
ctxId?.Dispose()
仍然会运行。一般来说,最佳实践是尽可能缩小变量的范围。 (在合理范围内,使用精细范围也会损害可读性)。如果这就是整个方法,就像您的情况一样,那就完全没问题了。

[ * ] 有一些异常是无法捕获的,例如 StackOverflowException。那时您必须依靠操作系统来进行任何清理。

© www.soinside.com 2019 - 2024. All rights reserved.