为什么此方法会导致代码分析错误 CA2000:调用 Dispose()

本文关键字:CA2000 调用 Dispose 错误 此方法 代码 为什么 | 更新日期: 2023-09-27 18:34:50

我正在使用"Microsoft最小规则"代码分析集构建我的项目,它为我提供了有关此方法的CA2000:

private Timer InitializeTimer(double intervalInSeconds)
{
    Timer timer = null;
    try
    {
        timer = new Timer { Interval = intervalInSeconds * 1000, Enabled = true };
        timer.Elapsed += timer_Elapsed;
        timer.Start();
    }
    catch
    {
         if (timer != null)
         {
             timer.Dispose();
         }
    }
    return timer;
}

此方法只是从以秒为单位的间隔创建新System.Timers.Timer。我有三个这样的计时器正在运行(每秒一个,每分钟一个,每半小时一个(。也许最好有一个计时器并检查已过的事件处理程序,无论已经过去了一分钟还是半小时,但我不知道,这在这个时候更容易,它是继承的代码,我还不想破坏一切。

这种方法给了我臭名昭著的

Warning 21  CA2000 : Microsoft.Reliability : In method 'TimerManager.InitializeTimer(double)', call System.IDisposable.Dispose on object '<>g__initLocal0' before all references to it are out of scope.

现在我打电话给处理渔获,认为这就足够了?我还在类自己的 IDisposable 实现中释放所有计时器。

我在这里错过了什么?

为什么此方法会导致代码分析错误 CA2000:调用 Dispose()

你只在出现异常的情况下调用Dispose(你永远不应该用一个包罗万象的块BTW来处理,但那是另一回事(。如果没有例外,则不会释放Timer对象。

添加finally块并将Dispose移动到该块,或使用using块。

警告告诉您正在创建一次性对象,而不是在所有情况下都将其处置。如果要以其他方法正确处理它,则可以安全地禁止显示此警告(可以使用 SuppressMessageAttribute 执行此操作(。

好的,我这样编辑它:

private Timer InitializeTimer(double intervalInSeconds)
    {
        Timer tempTimer = null;
        Timer timer;
        try
        {
            tempTimer = new Timer();
            tempTimer.Interval = intervalInSeconds * 1000;
            tempTimer.Enabled = true;
            tempTimer.Elapsed += timer_Elapsed;
            tempTimer.Start();
            timer = tempTimer;
            tempTimer = null;
        }
        finally
        {
            if (tempTimer != null)
            {
                tempTimer.Dispose();
            }
        }
        return timer;
    }

这是根据 CA2000 文档,它不会给出警告。我忽略了对象初始值设定项语法创建一个可能无法释放的临时对象这一事实。

谢谢,伙计们!

我认为使用"而不是"尝试/最终"引用要好得多

private Timer InitializeTimer(double intervalInSeconds)
{
    Timer timer;
    using (var tempTimer = new Timer())
    {
        tempTimer.Interval = intervalInSeconds * 1000;
        tempTimer.Enabled = true;
        tempTimer.Elapsed += timer_Elapsed;
        tempTimer.Start();
        timer = tempTimer;
    }
    return timer;
}