Algoritmy a programování IV

Týden 3

Dále implementujte MakeDeposit metody a MakeWithdrawal . Tyto metody vynucují poslední dvě pravidla: počáteční zůstatek musí být kladný a žádné stažení nesmí vytvořit záporný zůstatek.

Tato pravidla zavádějí koncept výjimek. Standardní způsob, jak indikovat, že metoda nemůže úspěšně dokončit svou práci, je vyvolat výjimku. Typ výjimky a zpráva, která je k ní přidružená, popisují chybu. Zde metoda vyvolá výjimku, MakeDeposit pokud výše vkladu není větší než 0. Metoda MakeWithdrawal vyvolá výjimku, pokud částka výběru není větší než 0 nebo pokud použití výběru vede k zápornému zůstatku. Za deklaraci _allTransactions seznamu přidejte následující kód:


public void MakeDeposit(decimal amount, DateTime date, string note)
{
    if (amount <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(amount), "Amount of deposit must be positive");
    }
    var deposit = new Transaction(amount, date, note);
    _allTransactions.Add(deposit);
}public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
    if (amount <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
    }
    if (Balance - amount < 0)
    {
        throw new InvalidOperationException("Not sufficient funds for this withdrawal");
    }
    var withdrawal = new Transaction(-amount, date, note);
    _allTransactions.Add(withdrawal);
}

Příkazthrowvyvolá výjimku. Provádění aktuálního bloku končí a řídí přenosy do prvního odpovídajícího catch bloku nalezeného v zásobníku volání. O něco později přidáte catch blok pro otestování tohoto kódu.

Konstruktor by měl získat jednu změnu, aby přidal počáteční transakci místo přímé aktualizace zůstatku. Vzhledem k tomu, že jste již napsali metodu MakeDeposit , zavolejte ji z konstruktoru. Dokončený konstruktor by měl vypadat takto:


public BankAccount(string name, decimal initialBalance)
{
    Number = s_accountNumberSeed.ToString();
    s_accountNumberSeed++;    Owner = name;
    MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
}

DateTime.Now je vlastnost, která vrací aktuální datum a čas. Otestujte tento kód přidáním několika vkladů a výběrů do metody Main podle kódu, který vytvoří nový BankAccount:


account.MakeWithdrawal(500, DateTime.Now, "Rent payment");
Console.WriteLine(account.Balance);
account.MakeDeposit(100, DateTime.Now, "Friend paid me back");
Console.WriteLine(account.Balance);

Dále otestujte, že zachytáváte chybové stavy tím, že se pokusíte vytvořit účet se záporným zůstatkem. Za předchozí kód, který jste právě přidali, přidejte následující kód:


// Test that the initial balances must be positive.
BankAccount invalidAccount;
try
{
    invalidAccount = new BankAccount("invalid", -55);
}
catch (ArgumentOutOfRangeException e)
{
    Console.WriteLine("Exception caught creating account with negative balance");
    Console.WriteLine(e.ToString());
    return;
}

Pomocítry-catch příkazu označíte blok kódu, který může vyvolat výjimky, a zachytíte chyby, které očekáváte. Stejný postup můžete použít k otestování kódu, který vyvolá výjimku pro záporný zůstatek. Před deklaraci invalidAccount ve vaší Main metodě přidejte následující kód:


// Test for a negative balance.
try
{
    account.MakeWithdrawal(750, DateTime.Now, "Attempt to overdraw");
}
catch (InvalidOperationException e)
{
    Console.WriteLine("Exception caught trying to overdraw");
    Console.WriteLine(e.ToString());
}

Uložte soubor a zadejte dotnet run , abyste ho vyzkoušeli.

Výzva – protokolování všech transakcí

Chcete-li dokončit tento kurz, můžete napsat metodu GetAccountHistory , která vytvoří string pro historii transakcí. Přidejte tuto metodu do BankAccount typu:


public string GetAccountHistory()
{
    var report = new System.Text.StringBuilder();    decimal balance = 0;
    report.AppendLine("Date\t\tAmount\tBalance\tNote");
    foreach (var item in _allTransactions)
    {
        balance += item.Amount;
        report.AppendLine($"{item.Date.ToShortDateString()}\t{item.Amount}\t{balance}\t{item.Notes}");
    }    return report.ToString();
}

Historie používá StringBuilder třídu k formátování řetězce, který obsahuje jeden řádek pro každou transakci. Kód formátování řetězců jste viděli dříve v těchto kurzech. Jeden nový znak je \t. Tím se vloží karta pro formátování výstupu.

Přidejte tento řádek a otestujte ho v souboru Program.cs:


Console.WriteLine(account.GetAccountHistory());

Výsledky zobrazíte spuštěním programu.