96 votes

Pourquoi cette condition (null || !TryParse) entraîne-t-elle "l'utilisation d'une variable locale non attribuée" ?

Le code suivant donne comme résultat utilisation d'une variable locale non affectée "numberOfGroups". :

int numberOfGroups;
if(options.NumberOfGroups == null || !int.TryParse(options.NumberOfGroups, out numberOfGroups))
{
    numberOfGroups = 10;
}

Cependant, ce code fonctionne bien (bien que, ReSharper dit le = 10 est redondant) :

int numberOfGroups = 10;
if(options.NumberOfGroups == null || !int.TryParse(options.NumberOfGroups, out numberOfGroups))
{
    numberOfGroups = 10;
}

J'ai raté quelque chose, ou bien le compilateur n'aime pas mes || ?

J'ai réduit la liste à dynamic causant les problèmes ( options La question reste posée, pourquoi je ne peux pas faire ça ?

Ce code n'a pas compiler :

internal class Program
{
    #region Static Methods

    private static void Main(string[] args)
    {
        dynamic myString = args[0];

        int myInt;
        if(myString == null || !int.TryParse(myString, out myInt))
        {
            myInt = 10;
        }

        Console.WriteLine(myInt);
    }

    #endregion
}

Cependant, ce code fait :

internal class Program
{
    #region Static Methods

    private static void Main(string[] args)
    {
        var myString = args[0]; // var would be string

        int myInt;
        if(myString == null || !int.TryParse(myString, out myInt))
        {
            myInt = 10;
        }

        Console.WriteLine(myInt);
    }

    #endregion
}

Je n'avais pas réalisé dynamic serait un facteur à prendre en compte.

72voto

Eric Lippert Points 300275

Je suis presque sûr que c'est un bug du compilateur. Belle découverte !

Voici une reproduction minimale :

class Program
{
    static bool M(out int x) 
    { 
        x = 123; 
        return true; 
    }
    static int N(dynamic d)
    {
        int y;
        if(d || M(out y))
            y = 10;
        return y; 
    }
}

Je ne vois pas pourquoi cela devrait être illégal ; si vous remplacez dynamic par bool, cela compile très bien.

En fait, je rencontre l'équipe C# demain ; je leur en parlerai. Toutes mes excuses pour cette erreur !

52voto

Quartermeister Points 24729

Il est possible que la variable ne soit pas affectée si la valeur de l'expression dynamique est d'un type avec un indicateur de type surchargé true opérateur .

El || invoquera l'opérateur true pour décider s'il faut évaluer le côté droit, puis l'opérateur if invoquera le true pour décider s'il faut évaluer son corps. Pour un bool Ces opérateurs renverront toujours le même résultat et un seul sera évalué, mais pour un opérateur défini par l'utilisateur, il n'y a pas de telle garantie !

En se basant sur le reproche d'Eric Lippert, voici un programme court et complet qui démontre un cas où aucun chemin ne serait exécuté et où la variable aurait sa valeur initiale :

using System;

class Program
{
    static bool M(out int x)
    {
        x = 123;
        return true;
    }

    static int N(dynamic d)
    {
        int y = 3;
        if (d || M(out y))
            y = 10;
        return y;
    }

    static void Main(string[] args)
    {
        var result = N(new EvilBool());
        // Prints 3!
        Console.WriteLine(result);
    }
}

class EvilBool
{
    private bool value;

    public static bool operator true(EvilBool b)
    {
        // Return true the first time this is called
        // and false the second time
        b.value = !b.value;
        return b.value;
    }

    public static bool operator false(EvilBool b)
    {
        throw new NotImplementedException();
    }
}

7voto

NominSim Points 5160

De MSDN (c'est moi qui souligne) :

Le type dynamique permet aux opérations dans lesquelles il intervient de contourner la vérification de type en temps de compilation . Au lieu de cela, ces opérations sont résolu au moment de l'exécution . Le type dynamique simplifie l'accès aux API COM, telles que les API de bureautique, ainsi qu'aux API dynamiques, telles que les bibliothèques IronPython, et au modèle d'objet de document HTML (DOM).

Le type dynamic se comporte comme le type object dans la plupart des circonstances. Toutefois, Les opérations qui contiennent des expressions de type dynamic ne sont pas résolues ou vérifiées par le compilateur.

Étant donné que le compilateur ne vérifie pas le type et ne résout pas les opérations qui contiennent des expressions de type dynamique, il ne peut pas garantir que la variable sera affectée par l'utilisation de la fonction TryParse() .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X