Ondes d’avertissement C#

De nouveaux avertissements et erreurs peuvent être introduits dans chaque version du compilateur C#. Si de nouveaux avertissements peuvent être signalés sur le code existant, ces avertissements sont introduits sous un système d’adhésion appelé onde d’avertissement. Le système d’adhésion signifie l'absence de nouveaux avertissements sur le code existant si vous n'avez pris aucune mesure pour les activer. Les ondes d’avertissement sont activées à l’aide de l’élément AnalysisLevel dans votre fichier projet. Quand <TreatWarningsAsErrors>true</TreatWarningsAsErrors> est spécifié, les avertissements d’onde d’avertissement activés génèrent des erreurs. L’onde d’avertissement 5 diagnostics a été ajoutée dans C# 9. L’onde d’avertissement 6 diagnostics a été ajoutée dans C# 10. L’onde d’avertissement 7 diagnostics a été ajoutée dans C# 11. Les diagnostics de la vague d’avertissement 8 ont été ajoutés dans C# 12.

CS9123 – La prise d’adresse d’un paramètre local ou d’un paramètre dans une méthode asynchrone peut créer un espace GC.

Vague d’avertissement 8

L’opérateur & ne doit pas être utilisé sur les paramètres ou les variables locales dans les méthodes asynchrones. Le code suivant génère l’erreur CS9123 :

public static async Task LogValue()
{
    int x = 1;
    unsafe {
        int* y = &x;
        Console.WriteLine(*y);
    }
    await Task.Delay(1000);
}

CS8981 : le nom de type contient uniquement des caractères ascii en minuscules.

Vague d’avertissement 7

Tous les nouveaux mots clés ajoutés pour C# seront tous des caractères ASCII minuscules. Cet avertissement permet qu’aucun de vos types n’entre en conflit avec des mots clés futurs. Le code suivant génère l’erreur CS8981 :

public class lowercasename
{
}

Vous pouvez résoudre cet avertissement en renommant le type pour inclure au moins un caractère ASCII autre qu’en minuscule, tel qu’une majuscule, un chiffre ou un trait de soulignement.

CS8826 : Les déclarations de méthode partielles présentent des différences de signature.

Vague d’avertissements 6

Cet avertissement corrige certaines incohérences dans la notification des différences entre les signatures de méthode partielle. Le compilateur signalait toujours une erreur lorsque les signatures de méthode partielle créaient différentes signatures CLR. À présent, le compilateur signale l’erreur CS8826 lorsque les signatures sont syntaxiquement différentes en C#. Prenons en considération le schéma partiel suivant :

public partial class PartialType
{
    public partial void M1(int x);

    public partial T M2<T>(string s) where T : struct;

    public partial void M3(string s);


    public partial void M4(object o);
    public partial void M5(dynamic o);
    public partial void M6(string? s);
}

L’implémentation de classe partielle suivante génère plusieurs exemples de CS8626 :

public partial class PartialType
{
    // Different parameter names:
    public partial void M1(int y) { }

    // Different type parameter names:
    public partial TResult M2<TResult>(string s) where TResult : struct => default;

    // Relaxed nullability
    public partial void M3(string? s) { }


    // Mixing object and dynamic
    public partial void M4(dynamic o) { }

    // Mixing object and dynamic
    public partial void M5(object o) { }

    // Note: This generates CS8611 (nullability mismatch) not CS8826
    public partial void M6(string s) { }
}

Notes

Si l’implémentation d’une méthode utilise un type référence non-nullable tandis que l’autre déclaration accepte des types référence nullables, CS8611 est généré au lieu de CS8826.

Pour corriger les instance de ces avertissements, assurez-vous que les deux signatures correspondent.

CS7023 : un type statique est utilisé dans une expression « est » ou « comme ».

Vague d’avertissement 5

Les expressions is et as renvoient toujours false pour un type statique, puisque vous ne pouvez pas créer d’instances d’un type statique. Le code suivant génère l’erreur CS7023 :

static class StaticClass
{
    public static void Thing() { }
}

void M(object o)
{
    // warning: cannot use a static type in 'is' or 'as'
    if (o is StaticClass)
    {
        Console.WriteLine("Can't happen");
    }
    else
    {
        Console.WriteLine("o is not an instance of a static class");
    }
}

Le compilateur signale cet avertissement, puisque le test de type ne peut jamais aboutir. Pour corriger cet avertissement, supprimez le test et tout code exécuté uniquement si le test réussit. Dans l’exemple précédent, la clause else est toujours exécutée. Le corps de la méthode peut être remplacé par cette seule ligne :

Console.WriteLine("o is not an instance of a static class");

CS8073 : le résultat de l’expression est toujours « false » (ou « true »).

Vague d’avertissement 5

Les opérateurs == et != renvoient toujours false (ou true) lors de la comparaison d’un instance d’un type struct à null. Le code suivant illustre cette méthode. Supposons que S est un struct définissant operator == et operator != :

class Program
{
    public static void M(S s)
    {
        if (s == null) { } // CS8073: The result of the expression is always 'false'
        if (s != null) { } // CS8073: The result of the expression is always 'true'
    }
}

struct S
{
    public static bool operator ==(S s1, S s2) => s1.Equals(s2);
    public static bool operator !=(S s1, S s2) => !s1.Equals(s2);
    public override bool Equals(object? other)
    {
        // Implementation elided
        return false;
    }
    public override int GetHashCode() => 0;

    // Other details elided...
}

Pour corriger cette erreur, supprimez la vérification null et le code s’exécutant si l’objet est null.

CS8848 : l’opérateur « from » ne peut pas être utilisé ici en raison de la priorité. Utilisez des parenthèses pour lever l’ambiguïté.

Vague d’avertissement 5

Les exemples ci-dessous illustrent cet avertissement. L’expression se lie incorrectement en raison de la priorité des opérateurs.

bool b = true;
var source = new Src();
b = true;
source = new Src();
var a = b && from c in source select c;
Console.WriteLine(a);

var indexes = new Src2();
int[] array = { 1, 2, 3, 4, 5, 6, 7 };
var range = array[0..from c in indexes select c];

Pour corriger cette erreur, placez des parenthèses autour de l’expression de requête :

bool b = true;
var source = new Src();
b = true;
source = new Src();
var a = b && (from c in source select c);
Console.WriteLine(a);

var indexes = new Src2();
int[] array = { 1, 2, 3, 4, 5, 6, 7 };
var range = array[0..(from c in indexes select c)];

Les membres doivent être entièrement assignés, utilisez une variable non attribuée (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)

Vague d’avertissement 5

Plusieurs avertissements améliorent l’analyse des affectations définies pour les types struct définis dans les assemblys importés. Tous ces nouveaux avertissements sont générés lorsqu’une struct dans un assembly importé inclut un champ inaccessible (généralement un champ private) d’un type de référence, comme illustré dans l’exemple suivant :

public struct Struct
{
    private string data = String.Empty;
    public Struct() { }
}

Les exemples suivants présentent les avertissements générés à partir de l’analyse d’affectation définie améliorée :

  • CS8880 : La propriété implémentée automatiquement « Propriété » doit être entièrement assignée avant que le contrôle ne soit renvoyé à l'appelant.
  • CS8881 : le champ « champ » doit être entièrement assigné avant que le contrôle soit renvoyé à l'appelant.
  • CS8882 : le paramètre de sortie « paramètre » doit être assigné avant que le contrôle ne quitte la méthode actuelle.
  • CS8883 : utilisation d'une propriété implémentée automatiquement « Propriété » éventuellement non assignée.
  • CS8884 : utilisation d’un champ potentiellement non assigné « Champ »
  • CS8885 : l'objet « ce » ne peut pas être utilisé avant l'attribution de tous ses champs.
  • CS8886 : utilisation du paramètre de sortie non assigné « Nom_paramètre ».
  • CS8887 : utilisation d’une variable locale non assignée « Nom_variable »
public struct DefiniteAssignmentWarnings
{
    // CS8880
    public Struct Property { get; }
    // CS8881
    private Struct field;

    // CS8882
    public void Method(out Struct s)
    {

    }

    public DefiniteAssignmentWarnings(int dummy)
    {
        // CS8883
        Struct v2 = Property;
        // CS8884
        Struct v3 = field;
        // CS8885:
        DefiniteAssignmentWarnings p2 = this;
    }

    public static void Method2(out Struct s1)
    {
        // CS8886
        var s2 = s1;
        s1 = default;
    }

    public static void UseLocalStruct()
    {
        Struct r1;
        var r2 = r1;
    }
}

Vous pouvez corriger l’un de ces avertissements en initialisant ou en attribuant à la struct importée sa valeur par défaut :

public struct DefiniteAssignmentNoWarnings
{
    // CS8880
    public Struct Property { get; } = default;
    // CS8881
    private Struct field = default;

    // CS8882
    public void Method(out Struct s)
    {
        s = default;
    }

    public DefiniteAssignmentNoWarnings(int dummy)
    {
        // CS8883
        Struct v2 = Property;
        // CS8884
        Struct v3 = field;
        // CS8885:
        DefiniteAssignmentNoWarnings p2 = this;
    }

    public static void Method2(out Struct s1)
    {
        // CS8886
        s1 = default;
        var s2 = s1;
    }

    public static void UseLocalStruct()
    {
        Struct r1 = default;
        var r2 = r1;
    }
}

CS8892 : la méthode ne sera pas utilisée en tant que point d’entrée, puisqu’une « méthode » de point d’entrée synchrone a été trouvée.

Vague d’avertissement 5

Cet avertissement est généré sur tous les candidats de point d’entrée asynchrone lorsque vous avez plusieurs points d’entrée valides, y compris des points d’entrée synchrones.

L’exemple suivant génère l’avertissement CS8892 :

public static void Main()
{
    RunProgram();
}

// CS8892
public static async Task Main(string[] args)
{
    await RunProgramAsync();
}

Notes

Le compilateur utilise toujours le point d’entrée synchrone. S’il existe plusieurs points d’entrée synchrones, vous obtenez une erreur du compilateur.

Pour corriger cet avertissement, supprimez ou renommez le point d’entrée asynchrone.

CS8897 : les types statiques ne peuvent pas être utilisés en tant que paramètres

Vague d’avertissement 5

Les membres d’une interface ne peuvent pas définir des paramètres dont le type est une classe statique. Le code suivant illustre à la fois CS8897 et CS8898 :

public static class Utilities
{
    // elided
}

public interface IUtility
{
    // CS8897
    public void SetUtility(Utilities u);

    // CS8898
    public Utilities GetUtility();
}

Pour corriger cet avertissement, modifiez le type de paramètre ou supprimez la méthode.

CS8898 : les types statiques ne peuvent pas être utilisés en tant que types de retour

Vague d’avertissement 5

Les membres d’une interface ne peuvent pas définir un type de retour correspondant à une classe statique. Le code suivant illustre à la fois CS8897 et CS8898 :

public static class Utilities
{
    // elided
}

public interface IUtility
{
    // CS8897
    public void SetUtility(Utilities u);

    // CS8898
    public Utilities GetUtility();
}

Pour corriger cet avertissement, modifiez le type de retour ou supprimez la méthode.