Rozwiązywanie ostrzeżeń związanych z using instrukcjami i using deklaracjami

W tym artykule opisano następujące błędy kompilatora:

  • CS0245: Destruktorów i object.Finalize nie można wywoływać bezpośrednio. Rozważ użycie IDisposable.Dispose jeśli jest dostępne.
  • CS0728: Prawdopodobnie nieprawidłowe przypisanie do zmiennej lokalnej, która jest argumentem w instrukcji "using" lub lock. Wywołanie Dispose lub odblokowanie nastąpi na oryginalnej wartości lokalnej zmiennej.
  • CS1674: typ używany w instrukcji using musi być niejawnie konwertowany na "System.IDisposable".
  • CS8410: "Typ używany w instrukcji asynchronicznej using musi być niejawnie konwertowany na "System.IAsyncDisposable" lub zaimplementować odpowiednią metodę "DisposeAsync".
  • CS8417: Typ używany w asynchronicznej instrukcji using musi implementować 'System.IAsyncDisposable' lub implementować właściwą metodę 'DisposeAsync'. Czy chodziło ci o 'using', a nie 'await using'?
  • CS8418: Typ użyty w instrukcji 'using' musi implementować "System.IDisposable". Czy chodziło o "await using" zamiast 'using'?
  • CS8647: Nie można używać zmiennej używającej bezpośrednio w sekcji przełącznika (rozważ użycie nawiasów klamrowych).
  • CS8648: Nie można przeskoczyć do miejsca po deklaracji using.
  • CS8649: Nie można przeskoczyć do miejsca przed deklaracją using w tym samym bloku.
  • CS9229: Modyfikatory nie mogą być umieszczane przy użyciu deklaracji.

Implementowanie funkcji IDisposable i IAsyncDisposable

Następujące błędy i ostrzeżenia kompilatora wskazują problemy z implementacją lub użyciem wzorca usuwania:

  • CS0245: Destruktory i object.Finalize nie mogą być wywoływane bezpośrednio. Rozważ wywołanie IDisposable.Dispose jeśli jest dostępne.
  • CS1674: typ używany w instrukcji using musi być niejawnie konwertowany na "System.IDisposable".
  • CS8410: Typ używany w instrukcji asynchronicznej using musi być niejawnie konwertowany na "System.IAsyncDisposable" lub implementować odpowiednią metodę "DisposeAsync".
  • CS8417: Typ używany w instrukcji asynchronicznej using musi implementować "System.IAsyncDisposable" lub zaimplementować odpowiednią metodę "DisposeAsync". Czy oznaczałeś "using", a nie "await using"?
  • CS8418: typ używany w instrukcji using musi implementować "System.IDisposable". Czy oznaczałeś "await using", a nie "using"?

Instrukcja using zapewnia właściwą dyspozycję zasobów na końcu using bloku. Aby użyć typu z instrukcją using , musi zaimplementować odpowiedni interfejs usuwania. W przypadku instrukcji synchronicznych using typ musi implementować element IDisposable. W przypadku instrukcji asynchronicznych await using typ musi implementować IAsyncDisposable.

  • Nie można wywołać finalizatora bezpośrednio (CS0245): Nie można bezpośrednio wywołać destruktora ani metody Object.Finalize. Mechanizm odśmiecania pamięci automatycznie wywołuje finalizatory, gdy obiekty nie są już referencjonowane. W celu oczyszczania deterministycznego zaimplementuj IDisposable i wywołaj metodę Dispose .
  • Typ musi implementować interfejs IDisposable (CS1674): tylko typy, które implementują IDisposable , mogą być używane w instrukcji using . Typy wartości nie implementują tego interfejsu, a parametry typu ogólnego bez odpowiednich ograniczeń nie mogą być uznawane za jednorazowe. Zastosuj ograniczenie typu, takie jak where T : IDisposable podczas pracy z typami ogólnymi.
  • Typ musi implementować IAsyncDisposable (CS8410): Typy używane z await using muszą implementować IAsyncDisposable lub zapewniać odpowiednią metodę DisposeAsync. Jeśli typ nie obsługuje usuwania asynchronicznego, użyj instrukcji synchronicznej using zamiast tego lub zaimplementuj wymagany interfejs.
  • Niezgodność wzorca usuwania (CS8417, CS8418): CS8417 występuje w przypadku użycia await using z typem, który implementuje tylko IDisposable. CS8418 występuje podczas używania synchronicznego using z typem, który implementuje tylko IAsyncDisposable. Dopasuj słowo kluczowe using do interfejsu, który implementuje twój typ, lub zaimplementuj oba interfejsy, jeśli chcesz obsługiwać oba wzorce.

Aby uzyskać więcej informacji, zobacz Finalizers, Implementowanie metody Dispose i Implementowanie metody DisposeAsync.

Korzystanie z zakresów zmiennych i przepływu sterowania

Następujące błędy i ostrzeżenia kompilatora odnoszą się do nieprawidłowego using użycia zmiennych w instrukcjach przepływu sterowania:

  • CS0728: Prawdopodobnie nieprawidłowe przypisanie do zmiennej lokalnej, która jest argumentem instrukcji using lub lock. Wywołanie Dispose lub odblokowanie nastąpi na oryginalnej wartości zmiennej.
  • CS8647: Nie można używać zmiennej używającej bezpośrednio w sekcji przełącznika (rozważ użycie nawiasów klamrowych).
  • CS8648: Nie można skoczyć do lokalizacji po deklaracji using.
  • CS8649: Do lokalizacji przed deklaracją using nie można się odwołać w tym samym bloku.

Zmienna zadeklarowana za pomocą using ma określone reguły zakresu, które uniemożliwiają przecieki zasobów. Kompilator wymusza te reguły w celu zapewnienia prawidłowego usuwania.

  • Przypisanie do zmiennej (CS0728): To ostrzeżenie wskazuje, że przypisano nową wartość do zmiennej, która jest zasobem w instrukcji using. Wywołanie usuwania odbywa się na wartości pierwotnej, a nie na nowo przypisanej wartości, co może prowadzić do wycieków zasobów. Zainicjuj zasób w deklaracji instrukcji using zamiast przypisywać go później.

  • Używanie zmiennej w sekcji switch (CS8647): using Deklaracja tworzy zmienną, która jest usuwana na końcu swojego zakresu. W przypadku użycia bezpośrednio w sekcji przełącznika bez nawiasów klamrowych zakres jest niejednoznaczny i może prowadzić do błędów. Otocz zawartość sekcji przełącznika nawiasami klamrowymi, aby jasno określić zakres.

  • Instrukcje goto i używanie deklaracji (CS8648, CS8649): Nie można używać goto instrukcji do przeskoczenia using deklaracji, ponieważ skoki pomijają właściwe zarządzanie zasobami. CS8648 występuje podczas przechodzenia do przodu przez deklarację using , a CS8649 występuje podczas przechodzenia do tyłu do lokalizacji przed deklaracją using . Zmień strukturę kodu, aby używał przepływu sterowania strukturalnego, takiego jak pętle, lub przenieś deklarację using poza obiekt docelowy skoku.

Aby uzyskać więcej informacji, zobacz instrukcję using.

Nieprawidłowa using deklaracja

  • CS9229: Modyfikatory nie mogą być umieszczane przy użyciu deklaracji.

Deklaracja zmiennej opakowana w deklarację using nie może zawierać żadnego z następujących modyfikatorów:

  • const
  • static
  • volatile
  • readonly
  • Modyfikatory ułatwień dostępu: public, protected, internal, private, protected internallub private protected

Poniższy przykład generuje 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() { }
}

Aby naprawić ten błąd, usuń modyfikator z deklaracji using :

using var resource = new Resource();

Aby uzyskać więcej informacji, zobacz using statement (instrukcja using).