通过


解决与 using 语句和 using 声明相关的警告

本文介绍以下编译器错误:

  • CS0245析构函数和object.Finalize不能直接调用。请考虑调用IDisposable.Dispose(如果可用)。
  • CS0728可能错误地将值赋给作为 using 或 lock 语句的参数的局部变量。调用 Dispose 或解锁将发生在该局部变量的原始值上。
  • CS1674在 using 语句中使用的类型必须能够隐式转换为“System.IDisposable”。
  • CS8410异步 using 语句中使用的类型必须隐式转换为“”System.IAsyncDisposable或实现合适的“”DisposeAsync方法。
  • CS8417在异步 using 语句中使用的类型必须实现 'System.IAsyncDisposable' 或实现合适的 'DisposeAsync' 方法。你的意思是 'using' 而不是 'await using'?
  • CS8418using 语句中使用的类型必须实现“System.IDisposable”。如果你的意思是“await using”而不是“using”吗?
  • CS8647不能直接在 switch 语句块中使用 using 变量(请考虑使用大括号)。
  • CS8648使用 goto 声明后无法跳转到某个位置。
  • CS8649:不能跳转到同一块中使用声明之前的某个位置。
  • CS9229不能使用声明放置修饰符。

实现 IDisposable 和 IAsyncDisposable

以下编译器错误和警告指示实现或使用释放模式时出现问题:

  • CS0245析构函数和object.Finalize不能被直接调用。请考虑调用IDisposable.Dispose(如果可用)。
  • CS1674在 using 语句中使用的类型必须能够隐式转换为“System.IDisposable”。
  • CS8410异步 using 语句中使用的类型必须隐式转换为“”System.IAsyncDisposable或实现合适的“DisposeAsync”方法。
  • CS8417异步 using 语句中使用的类型必须实现“”System.IAsyncDisposable或实现合适的“”DisposeAsync方法。你的意思是'using'而不是''await using
  • CS8418using 语句中使用的类型必须实现System.IDisposable。是否意味着使用'await using'而不是'using'?

using 语句可确保在using块结束时正确处置资源。 若要对 using 语句使用类型,它必须实现适当的处置接口。 对于同步 using 语句,类型必须实现 IDisposable。 对于异步 await using 语句,类型必须实现 IAsyncDisposable

  • 无法直接调用 Finalize(CS0245):不能直接调用析构函数或 Object.Finalize 方法。 当对象不再被引用时,垃圾回收器会自动执行终止器。 对于确定性清理,请改为实现 IDisposable 和调用 Dispose 该方法。
  • 类型必须实现 IDisposable(CS1674):只有实现IDisposable的类型才能在using语句中使用。 值类型不实现此接口,不能假定没有适当约束的泛型类型参数是可释放的。 在使用泛型类型时,应用类型约束,例如 where T : IDisposable
  • 类型必须实现 IAsyncDisposable (CS8410):await using 一起使用的类型必须实现 IAsyncDisposable 或提供适当的 DisposeAsync 方法。 如果类型不支持异步处置,请改用同步 using 语句或实现所需的接口。
  • 不匹配的处置模式(CS8417,CS8418): 当您与仅实现IDisposable的类型一起使用await using时,会发生 CS8417。 将同步 using 用于仅实现 IAsyncDisposable的类型时,会发生 CS8418。 将 using 关键字与类型实现的接口匹配,或者如果需要支持这两种模式,则实现这两个接口。

有关详细信息,请参阅 终结器实现 Dispose 方法实现 DisposeAsync 方法

使用变量范围和控制流

以下编译器错误和警告与控制流语句中变量的 using 不正确用法相关:

  • CS0728可能对局部变量进行不正确的赋值,该变量是usinglock语句的参数。Dispose调用或解锁将在该局部变量的原始值上发生。
  • CS8647不能直接在 switch 语句块中使用 using 变量,建议使用大括号。
  • CS8648使用 goto 声明后无法跳转到某个位置。
  • CS8649goto不能跳转到同一代码块内using声明之前的位置。

使用 using 特定范围规则声明的变量可阻止资源泄漏。 编译器强制实施这些规则,以确保正确处置。

  • 赋值到使用变量(CS0728):此警告表明你将一个新值赋给了 using 语句中的资源变量。 释放调用发生在原始值上,而不是新分配的值,这可能会导致资源泄漏。 在using声明语句中初始化资源,而不是将其分配到稍后的语句中。

  • 在 switch 节中使用变量(CS8647)using 声明创建了一个在其范围结束时释放的变量。 直接在没有大括号的 switch 语句中使用时,范围不明确,可能导致歧义和错误。 将 switch 节内容用大括号括起来以明确其范围。

  • Goto 语句和使用声明(CS8648、CS8649):不能使用 goto 语句跳转 using 声明,因为跳转会跳过适当的资源管理。 CS8648 发生在向前跳过 using 声明时,CS8649 发生在向后跳转到 using 声明之前的位置时。 重构代码以使用结构化控制流(如循环)或将 using 声明移到跳转目标之外。

有关详细信息,请参阅 using 语句

声明不正确using

  • CS9229不能在 using 声明上使用修饰符。

包含在 using 声明中的变量声明不能包括以下任何修饰符:

  • const
  • static
  • volatile
  • readonly
  • 辅助功能修饰符:publicprotectedinternalprivateprotected internalprivate protected

以下示例生成 CS9229:

using System;

class Program
{
    static void Main()
    {
        // error CS9229: Modifiers cannot be placed on using declarations.
        public using var resource = new Resource();

        // error CS9229: Modifiers cannot be placed on using declarations.
        static using var anotherResource = new Resource();
    }
}

class Resource : IDisposable
{
    public void Dispose() { }
}

若要更正此错误,请从 using 声明中删除修饰符:

using var resource = new Resource();

有关详细信息,请参阅 using 语句