web-dev-qa-db-fra.com

Que signifie "Utilisation de variable locale non affectée"?

Je continue à recevoir cette erreur pour AnnualRate, MonthlyCharge et lateFee.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Lab_5___Danny_Curro
{
    class Program
    {
        static void Main(string[] args)
        {
            string firstName;
            string lastName;
            int accNumber;
            string creditPlan;
            double balance;
            string status;
            Boolean late = false;
            double lateFee;
            double monthlyCharge;
            double annualRate;
            double netBalance;


            Console.Write("Enter First Name: ");
            firstName = Console.ReadLine();

            Console.Write("Enter Last Name: ");
            lastName = Console.ReadLine();

            Console.Write("Enter Account Number: ");
            accNumber = Convert.ToInt32(Console.ReadLine());


            Console.Write("Enter Credit Card Plan Number[Blank Will Enter Plan 0]: ");
            creditPlan = Console.ReadLine();

            Console.Write("Enter Balance: ");
            balance = Convert.ToDouble(Console.ReadLine());

            Console.Write("Is This Account Late?: ");
            status = Console.ReadLine().Trim().ToLower();

            if (creditPlan == "0")
            {
                annualRate = 0.35;  //35%
                lateFee = 0.0;
                monthlyCharge = balance * (annualRate * (1 / 12));
                return;
            }

            if (creditPlan == "1")
            {
                annualRate = 0.30;  //30%
                if (status == "y")
                {
                    late = true;
                }

                else if (status == "n")
                {
                    late = false;
                }
                if (late == true)
                {
                    lateFee = 25.00;
                }
                monthlyCharge = balance * (annualRate * (1 / 12));
                return;
            }
            if (creditPlan == "2")
            {
                annualRate = 0.20;  //20%
                if (status == "y")
                {
                    late = true;
                }

                else if (status == "n")
                {
                    late = false;
                }
                if (late == true)
                {
                    lateFee = 35.00;
                }
                if (balance > 100)
                {
                    monthlyCharge = balance * (annualRate * (1 / 12));
                }
                else
                {
                    monthlyCharge = 0;
                }
                return;
            }
            if (creditPlan == "3")
            {
                annualRate = 0.15;  //15%
                lateFee = 0.00;

                if (balance > 500)
                {
                    monthlyCharge = (balance - 500) * (annualRate * (1 / 12));
                }
                else
                {
                    monthlyCharge = 0;
                }
                return;
            }
            netBalance = balance - (lateFee + monthlyCharge);


            Console.WriteLine("Name: \t\t\t {0}  {1}", firstName, lastName);
            Console.WriteLine("Account Number: \t{0}", accNumber);
            Console.WriteLine("Credit Plane: \t\t{0}",creditPlan);
            Console.WriteLine("Account Late: \t\t{0}", late);
            Console.WriteLine("Balance: \t\t{0}", balance);
            Console.WriteLine("Late Fee: \t\t{0}", lateFee);
            Console.WriteLine("Interest Charge: \t{0}", monthlyCharge);
            Console.WriteLine("Net Balance: \t\t{0}",netBalance);
            Console.WriteLine("Annual Rate: \t\t{0}", annualRate);
            Console.ReadKey();
        }
    }
}
26
Daniel Curro

Le compilateur n'est pas assez intelligent pour savoir qu'au moins un de vos blocs if sera exécuté. Par conséquent, il ne voit pas que des variables telles que annualRate seront affectées quoi qu'il arrive. Voici comment vous pouvez faire comprendre le compilateur:

if (creditPlan == "0")
{
    // ...
}
else if (creditPlan == "1")
{
    // ...
}
else if (creditPlan == "2")
{
    // ...
}
else
{
    // ...
}

Le compilateur sait qu'avec un bloc if/else, l'exécution de l'un des blocs est garantie. Par conséquent, si vous affectez la variable dans tous les blocs, le compilateur n'aura pas d'erreur.

En passant, vous pouvez également utiliser une instruction switch au lieu de ifs pour éventuellement rendre votre code plus propre.

49
Jacob

Changez vos déclarations en ceci:

double lateFee = 0.0;
double monthlyCharge = 0.0;
double annualRate = 0.0;

L'erreur est due au fait qu'il existe au moins un chemin dans votre code où ces variables ne sont finalement pas définies.

14
Kyle Trauberman

Parce que si aucune des instructions if n'est évaluée à true, la variable locale sera non affectée. Ajoutez une autre instruction et attribuez des valeurs à ces variables au cas où l'instruction if ne serait pas vraie. Postez ici si cela ne fait pas disparaître l'erreur.

Votre autre option consiste à initialiser les variables à une valeur par défaut lorsque vous les déclarez au début de votre code.

10
Pete

Donnez-leur une valeur par défaut:

double lateFee=0.0;
double monthlyCharge = 0.0;
double annualRate = 0.0;

Fondamentalement, tous les chemins possibles n'initialisent pas ces variables.

7
manojlds

Vos affectations sont toutes imbriquées dans votre conditionnel si bloque, ce qui signifie qu'il est possible qu'elles ne soient jamais attribuées. 

Au sommet de votre classe, initialisez-les à 0 ou à une autre valeur

3
lomaxx

Votre code comporte de nombreux chemins dans lesquels vos variables ne sont pas initialisées, raison pour laquelle le compilateur se plaint.

Plus précisément, vous ne validez pas la saisie de l'utilisateur pour creditPlan - si l'utilisateur entre une valeur autre que "0","1","2" or "3", aucune des branches indiquées ne sera exécutée (et creditPlan ne sera pas mis à zéro comme indiqué dans l'invite de l'utilisateur). 

Comme d'autres l'ont mentionné, l'erreur du compilateur peut être évitée soit par une initialisation par défaut de toutes les variables dérivées avant la vérification des branches, OR en s'assurant qu'au moins une des branches est exécutée (à savoir l'exclusivité mutuelle des branches, avec une chute dans la déclaration else).

J'aimerais toutefois souligner d'autres améliorations potentielles:

  • Validez la saisie de l'utilisateur avant de lui faire confiance pour l'utiliser dans votre code.
  • Modélisez les paramètres dans leur ensemble - il existe plusieurs propriétés et calculs applicables à chaque plan.
  • Utilisez des types plus appropriés pour les données. par exemple. CreditPlan semble avoir un domaine fini et convient mieux à enumeration ou Dictionary qu'à string. Les données financières et les pourcentages doivent toujours être modélisés sous la forme decimal et non double pour éviter les problèmes d'arrondi, et le 'statut' semble être un booléen.
  • Sécher le code répétitif. Le calcul, monthlyCharge = balance * annualRate * (1/12)), est commun à plusieurs branches. Pour des raisons de maintenance, ne dupliquez pas ce code.
  • Peut-être plus avancé, mais notez que les fonctions sont maintenant des citoyens de première classe de C #, vous pouvez donc affecter une fonction ou un lambda en tant que propriété, champ ou paramètre !.

par exemple. voici une représentation alternative de votre modèle:

    // Keep all Credit Plan parameters together in a model
    public class CreditPlan
    {
        public Func<decimal, decimal, decimal> MonthlyCharge { get; set; }
        public decimal AnnualRate { get; set; }
        public Func<bool, Decimal> LateFee { get; set; }
    }

    // DRY up repeated calculations
    static private decimal StandardMonthlyCharge(decimal balance, decimal annualRate)
    { 
       return balance * annualRate / 12;
    }

    public static Dictionary<int, CreditPlan> CreditPlans = new Dictionary<int, CreditPlan>
    {
        { 0, new CreditPlan
            {
                AnnualRate = .35M, 
                LateFee = _ => 0.0M, 
                MonthlyCharge = StandardMonthlyCharge
            }
        },
        { 1, new CreditPlan
            {
                AnnualRate = .30M, 
                LateFee = late => late ? 0 : 25.0M,
                MonthlyCharge = StandardMonthlyCharge
            }
        },
        { 2, new CreditPlan
            {
                AnnualRate = .20M, 
                LateFee = late => late ? 0 : 35.0M,
                MonthlyCharge = (balance, annualRate) => balance > 100 
                    ? balance * annualRate / 12
                    : 0
            }
        },
        { 3, new CreditPlan
            {
                AnnualRate = .15M, 
                LateFee = _ => 0.0M,
                MonthlyCharge = (balance, annualRate) => balance > 500 
                    ? (balance - 500) * annualRate / 12
                    : 0
            }
        }
    };
2
StuartLC

Le compilateur dit que annualRate n'aura pas de valeur si le plan de crédit n'est pas reconnu.

Lors de la création des variables locales (annualRate, MonthlyCharge et lateFee), affectez-leur une valeur par défaut (0).

En outre, vous devez afficher une erreur si le plan de crédit est inconnu.

1
Richard Schneider

Tous les chemins de code ne définissent pas une valeur pour lateFee. Vous voudrez peut-être définir une valeur par défaut pour le haut.

0
Andrew Cooper

Vous n'attribuez pas de valeurs en dehors des déclarations if ... et il est possible que le crédit soit différent de 0, 1, 2 ou 3, comme l'a noté @iomaxx.

Essayez de changer les instructions if distinctes en un seul if/else if/else if/else. Ou assigner des valeurs par défaut en haut.

0
David

Si vous déclarez la variable "annualRate" comme

programme de classe {

**static double annualRate;**

public static void Main() {

Essayez-le ..

0
Manoilayans