Daniel Curro
Daniel Curro

Reputation: 513

What does "Use of unassigned local variable" mean?

I keep getting this error for annualRate, monthlyCharge, and 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();
        }
    }
}

Upvotes: 51

Views: 302070

Answers (11)

Daniel Cipolla Vasquez
Daniel Cipolla Vasquez

Reputation: 161

Use the keyword "default"!!!

    string myString = default;
    double myDouble = default;

    if(!String.IsNullOrEmpty(myString))
       myDouble = 1.5;

    return myDouble;

Upvotes: 12

StuartLC
StuartLC

Reputation: 107267

There are many paths through your code whereby your variables are not initialized, which is why the compiler complains.

Specifically, you are not validating the user input for creditPlan - if the user enters a value of anything else than "0","1","2" or "3", then none of the branches indicated will be executed (and creditPlan will not be defaulted to zero as per your user prompt).

As others have mentioned, the compiler error can be avoided by either a default initialization of all derived variables before the branches are checked, OR ensuring that at least one of the branches is executed (viz, mutual exclusivity of the branches, with a fall through else statement).

I would however like to point out other potential improvements:

  • Validate user input before you trust it for use in your code.
  • Model the parameters as a whole - there are several properties and calculations applicable to each plan.
  • Use more appropriate types for data. e.g. CreditPlan appears to have a finite domain and is better suited to an enumeration or Dictionary than a string. Financial data and percentages should always be modelled as decimal, not double to avoid rounding issues, and 'status' appears to be a boolean.
  • DRY up repetitive code. The calculation, monthlyCharge = balance * annualRate * (1/12)) is common to more than one branch. For maintenance reasons, do not duplicate this code.
  • Possibly more advanced, but note that Functions are now first class citizens of C#, so you can assign a function or lambda as a property, field or parameter!.

e.g. here is an alternative representation of your model:

    // 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
            }
        }
    };

Upvotes: 4

manojlds
manojlds

Reputation: 301167

Give them a default value:

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

Basically, all possible paths don't initialize these variables.

Upvotes: 12

Manoilayans
Manoilayans

Reputation: 25

If you declare the variable "annualRate" like

class Program {

**static double annualRate;**

public static void Main() {

Try it..

Upvotes: 0

David
David

Reputation: 2272

You don't assign values outside of the if statements ... and it is possible that credit might be something other than 0, 1, 2, or 3, as @iomaxx noted.

Try changing the separate if statements to a single if/else if/else if/else. Or assign default values up at the top.

Upvotes: 0

Andrew Cooper
Andrew Cooper

Reputation: 32576

Not all code paths set a value for lateFee. You may want to set a default value for it at the top.

Upvotes: 0

Jacob
Jacob

Reputation: 78840

The compiler isn't smart enough to know that at least one of your if blocks will be executed. Therefore, it doesn't see that variables like annualRate will be assigned no matter what. Here's how you can make the compiler understand:

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

The compiler knows that with an if/else block, one of the blocks is guaranteed to be executed, and therefore if you're assigning the variable in all of the blocks, it won't give the compiler error.

By the way, you can also use a switch statement instead of ifs to maybe make your code cleaner.

Upvotes: 71

Richard Schneider
Richard Schneider

Reputation: 35477

The compiler is saying that annualRate will not have a value if the CreditPlan is not recognised.

When creating the local variables ( annualRate, monthlyCharge, and lateFee) assign a default value (0) to them.

Also, you should display an error if the credit plan is unknown.

Upvotes: 1

Kyle Trauberman
Kyle Trauberman

Reputation: 25684

Change your declarations to this:

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

The error is caused because there is at least one path through your code where these variables end up not getting set to anything.

Upvotes: 20

lomaxx
lomaxx

Reputation: 115793

Your assignments are all nested within your conditional if blocks which means that there is potential for them to never be assigned.

At the top of your class, initialise them to 0 or some other value

Upvotes: 3

Pete
Pete

Reputation: 10871

Because if none of the if statements evaluate to true then the local variable will be unassigned. Throw an else statement in there and assign some values to those variables in case the if statements don't evaluate to true. Post back here if that doesn't make the error go away.

Your other option is to initialize the variables to some default value when you declare them at the beginning of your code.

Upvotes: 12

Related Questions