Что означает "использование неназначенной локальной переменной"?
Я продолжаю получать эту ошибку для annualRate, monthlyCharge и 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: ttt {0} {1}", firstName, lastName);
Console.WriteLine("Account Number: t{0}", accNumber);
Console.WriteLine("Credit Plane: tt{0}",creditPlan);
Console.WriteLine("Account Late: tt{0}", late);
Console.WriteLine("Balance: tt{0}", balance);
Console.WriteLine("Late Fee: tt{0}", lateFee);
Console.WriteLine("Interest Charge: t{0}", monthlyCharge);
Console.WriteLine("Net Balance: tt{0}",netBalance);
Console.WriteLine("Annual Rate: tt{0}", annualRate);
Console.ReadKey();
}
}
}
10 ответов
компилятор недостаточно умен, чтобы знать, что по крайней мере один из ваших if
блоки будут выполнены. Поэтому он не видит, что переменные типа annualRate
будет назначен независимо от того, что. Вот как вы можете заставить компилятор понять:
if (creditPlan == "0")
{
// ...
}
else if (creditPlan == "1")
{
// ...
}
else if (creditPlan == "2")
{
// ...
}
else
{
// ...
}
компилятор знает, что с блоком if/else один из блоков гарантированно будет выполнен, и поэтому, если вы назначаете переменную во всех блоках, она не даст ошибку компилятора.
по кстати, вы также можете использовать switch
заявление вместо if
s, чтобы, возможно, сделать ваш код чище.
измените свои объявления на это:
double lateFee = 0.0;
double monthlyCharge = 0.0;
double annualRate = 0.0;
ошибка вызвана тем, что существует по крайней мере один путь через ваш код, где эти переменные в конечном итоге не получают ничего.
потому что если ни один из операторов if является true, то переменной будет присвоено. Бросьте туда оператор else и назначьте некоторые значения этим переменным в случае, если операторы if не оцениваются как true. Сообщение здесь, если это не сделает ошибку уйти.
другой вариант-инициализировать переменные до некоторого значения по умолчанию при их объявлении в начале кода.
дать им значение по умолчанию:
double lateFee=0.0;
double monthlyCharge = 0.0;
double annualRate = 0.0;
в принципе, все возможные пути не инициализируют эти переменные.
все ваши назначения вложены в ваши условные блоки if, что означает, что существует вероятность того, что они никогда не будут назначены.
в верхней части класса инициализируйте их до 0 или другого значения
в вашем коде есть много путей, по которым ваши переменные не инициализируются, поэтому компилятор жалуется.
в частности, вы не проверяете ввод пользователя для creditPlan
- если пользователь вводит значение чего-либо, кроме "0","1","2" or "3"
, тогда ни одна из указанных ветвей не будет выполнена (и creditPlan
не будет по умолчанию равно нулю в соответствии с вашим приглашением пользователя).
как уже упоминалось, ошибки компилятора можно избежать либо по умолчанию инициализация всех производных переменных перед проверкой ветвей или обеспечение выполнения хотя бы одной из ветвей (а именно, взаимная исключительность ветвей, с провалом else
заявления).
однако я хотел бы указать на другие потенциальные улучшения:
- проверка ввода пользователя, прежде чем доверять ему для использования в коде.
- моделируйте параметры в целом - существует несколько свойств и расчетов, применимых к каждому плану.
- используйте более подходящие типы для данных. например,
CreditPlan
кажется, имеет конечную область и лучше подходит дляenumeration
илиDictionary
чемstring
. Финансовые данные и проценты всегда должны быть смоделированы какdecimal
, а неdouble
чтобы избежать проблем округления, а "статус", похоже, является логическим. - высушить повторяющийся код. Расчет,
monthlyCharge = balance * annualRate * (1/12))
является общим для более чем одной ветви. По причинам обслуживания не дублируйте это код. - возможно, более продвинутые, но обратите внимание, что функции теперь являются гражданами первого класса C#, поэтому вы можете назначить функцию или лямбду в качестве свойства, поля или параметра!.
например, вот альтернативное представление вашей модели:
// 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
}
}
};
компилятор говорит, что annualRate не будет иметь значения, если CreditPlan не распознается.
при создании локальных переменных (annualRate, monthlyCharge и lateFee) им присваивается значение по умолчанию (0).
кроме того, вы должны отобразить ошибку, если кредитный план неизвестен.
Не все пути кода установите значение lateFee
. Вы можете установить значение по умолчанию для него в верхней части.
вы не назначаете значения вне операторов if ... и возможно, что кредит может быть чем-то иным, чем 0, 1, 2 или 3, Как отметил @iomaxx.
попробуйте изменить отдельные операторы if на один if/else if/else if / else if / else. Или назначьте значения по умолчанию вверху.
Если вы объявите переменную "annualRate" как
программы класс {
**static double annualRate;**
public static void Main() {
попробовать его..