web-dev-qa-db-ja.com

「未割り当てのローカル変数の使用」とはどういう意味ですか?

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: \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();
        }
    }
}
29
Daniel Curro

コンパイラは、少なくとも1つのifブロックが実行されることを知るほど賢くありません。したがって、annualRateのような変数が何であれ割り当てられることはありません。コンパイラに理解させる方法は次のとおりです。

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

コンパイラは、if/elseブロックを使用すると、ブロックの1つが実行されることが保証されているため、すべてのブロックで変数を割り当てている場合、コンパイラエラーは発生しません。

ちなみに、switchsの代わりにifステートメントを使用して、コードをきれいにすることもできます。

55
Jacob

宣言をこれに変更します。

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

エラーが発生するのは、これらの変数が何も設定されないコードのパスが少なくとも1つあるためです。

15
Kyle Trauberman

Ifステートメントのいずれもがtrueと評価されない場合、ローカル変数は割り当てられないためです。そこにelseステートメントをスローし、ifステートメントがtrueと評価されない場合にそれらの変数にいくつかの値を割り当てます。エラーが解消されない場合は、ここに投稿してください。

他のオプションは、コードの先頭で変数を宣言するときに変数をデフォルト値に初期化することです。

11
Pete

それらにデフォルト値を与えます:

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

基本的に、すべての可能なパスはこれらの変数を初期化しません。

9
manojlds

割り当てはすべて条件付きifブロック内にネストされているため、割り当てられない可能性があります。

クラスの先頭で、それらを0または他の値に初期化します

3
lomaxx

あなたの変数が初期化されないコードを通る多くのパスがあります。それがコンパイラが文句を言う理由です。

具体的には、creditPlanのユーザー入力を検証していません。ユーザーが_"0","1","2" or "3"_以外の値を入力した場合、示されたブランチは実行されません(およびcreditPlanユーザープロンプトごとにゼロにデフォルト設定されることはありません)。

他の人が言及したように、分岐がチェックされる前にすべての派生変数のデフォルトの初期化、または分岐の少なくとも1つが実行されることを保証するOR分岐の排他性、フォールスルーelseステートメント)。

ただし、他の潜在的な改善点を指摘したいと思います。

  • コードで使用するために信頼する前に、ユーザー入力を検証します。
  • 全体としてパラメータをモデル化します-各計画に適用可能ないくつかのプロパティと計算があります。
  • より適切なタイプのデータを使用してください。例えばCreditPlanは有限領域を持つように見え、enumerationよりもDictionaryまたはstringに適しています。財務データとパーセンテージは、丸め問題を回避するために、decimalではなく、常にdoubleとしてモデル化する必要があり、 'status'はブール値のように見えます。
  • 繰り返しコードを乾燥させます。計算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
            }
        }
    };
_
2
StuartLC

コンパイラーは、CreditPlanが認識されない場合、annualRateには値がないと言っています。

ローカル変数(annualRate、monthlyCharge、lateFee)を作成するとき、それらにデフォルト値(0)を割り当てます。

また、与信計画が不明な場合はエラーを表示する必要があります。

1

すべてのコードパスがlateFeeの値を設定するわけではありません。上部でデフォルト値を設定することもできます。

0
Andrew Cooper

Ifステートメント以外の値を割り当てないでください... @iomaxxが指摘したように、クレジットが0、1、2、または3以外のものになる可能性があります。

個別のifステートメントを単一のif/else if/else if/elseに変更してみてください。または、デフォルト値を上部に割り当てます。

0
David

次のように変数「annualRate」を宣言すると

クラスProgram {

**static double annualRate;**

public static void Main() {

それを試してみてください..

0
Manoilayans