Как создать и обработать несколько исключений в Windows Forms? - PullRequest
0 голосов
/ 28 октября 2018

В приведенном ниже коде, который работает, я хотел бы обработать 5 различных исключений, которые могут быть созданы пользовательским вводом.

Я понимаю, что должен использовать оператор IF для обработки этихисключения, но требование заключается в обработке ошибок с помощью обработчиков исключений.Поэтому, пожалуйста, я ищу только входные данные для этого, а не альтернативы.
Я хотел бы обработать их с помощью обработчиков исключений.

Проблема, с которой я столкнулся, заключается в том, где разместить код обработки исключений..
Кроме того, наличие у меня 5 исключений, которые я хочу проверить, означает ли это, что мне нужно 5 различных блоков try/catch или я могу обработать их все в одном блоке?

Я являюсь исключениямиищите, пытаетесь создать более 19 учетных записей, пытаетесь создать учетную запись с начальным балансом ниже $300, снимаете со счета больше, чем текущий баланс, пытаетесь совершить транзакцию на учетной записи, которая еще не была создана, и вводитечто-либо кроме числа в TextBox.

Так что, если пользователь делает одну из этих ошибок, я бы хотел выбросить ошибку и показать пользователю сообщение об ошибке, которую он сделал.
Любая помощь очень ценится.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MoreRobustBankGUI
{       
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private int _nextIndex = 0;
        List<Account> accounts = new List<Account>();
        decimal balance = 0;
        private void createButton1_Click(object sender, EventArgs e)
        {
            if (accounts.Count < 19 && balance > 300)
            {
                _nextIndex++;
                int accountId = _nextIndex;
                decimal.TryParse(amountTextBox2.Text, out balance);

                transactionLabel3.Text = "Account: #" + accountId + " created with a starting balance of $" + balance;
                accountTextBox1.Text = "" + accountId;

                accounts.Add(new Account(balance)
                {
                    AccountId = accountId
                });
            }
            else
            {
                transactionLabel3.Text = "Can only create up to 19 accounts and starting balance must be $300";
            }
        }

        private void executeButton2_Click(object sender, EventArgs e)
        {
            decimal amount = 0;
            int accountID;

            string textAmount = amountTextBox2.Text == "" ? "0" : amountTextBox2.Text;

            if (depositRadioButton3.Checked == true)
            {
                if (string.IsNullOrEmpty(accountTextBox1.Text)) return;

                bool accountCanBeConverted = int.TryParse(accountTextBox1?.Text, out accountID);
                bool ammountCanBeConverted = decimal.TryParse(amountTextBox2?.Text, out amount);
                if (accountCanBeConverted && ammountCanBeConverted && amount > 0)
                {
                    var selectedAccount = GetAccount(accountID);
                    selectedAccount.DepositFunds(amount);
                    transactionLabel3.Text = $"Account: #{selectedAccount.AccountId} You made a deposit of ${amount}";
                }

            }
            else if (withdrawRadioButton2.Checked == true)
            {
                if (string.IsNullOrEmpty(accountTextBox1.Text)) return;

                bool accountCanBeConverted = int.TryParse(accountTextBox1?.Text, out accountID);
                bool ammountCanBeConverted = decimal.TryParse(amountTextBox2?.Text, out amount);
                if (accountCanBeConverted && ammountCanBeConverted && amount > 0)
                {
                    var selectedAccount = GetAccount(accountID);
                    if (selectedAccount.HasAvailableFunds)
                    {
                        selectedAccount.WithdrawFromAccount(amount);
                        transactionLabel3.Text = $"Account: #{selectedAccount.AccountId} You made a withdrawal of ${amount}";
                    }
                    else
                    {
                        transactionLabel3.Text = $"Account: #{selectedAccount.AccountId} Does not have available funds to withdraw";
                    }
                }
            }
            else if (balanceRadioButton3.Checked == true)
            {
                if (string.IsNullOrEmpty(accountTextBox1.Text)) return;

                bool accountCanBeConverted = int.TryParse(accountTextBox1?.Text, out accountID);

                var selectedAccount = GetAccount(accountID);
                var balance = selectedAccount.GetAvailableBalanceForAccount(accountID);

                if (balance == -1234567890)
                {
                    transactionLabel3.Text = $"Invalid account number passed.";
                }
                else
                {
                    transactionLabel3.Text = $"Account: #{selectedAccount.AccountId} Balance: $ {selectedAccount.GetAvailableBalanceForAccount(accountID)}";
                }
            }

            clearFields();
        }

        public void clearFields()
        {
            amountTextBox2.Text = "";
        }
        public Account GetAccount(int id)
        {
            return accounts.Where(x => x.AccountId == id).FirstOrDefault();
        }

        public class Account
        {

            public Account(decimal balance)
            {
               Balance = balance;
            }

            public int AccountId { get; set; }

            public decimal Balance { get; set; }

            public void WithdrawFromAccount(decimal deductionAmount)
            {
                Balance -= deductionAmount;
            }

            public void DepositFunds(decimal depositAmount)
            {
                Balance += depositAmount;
            }

            public bool HasAvailableFunds => Balance > 0;

            public decimal GetAvailableBalanceForAccount(int accountId)
            {
                if (accountId == AccountId)
                {
                    return Balance;
                }
                else
                {
                    return -1234567890;
                }
            }
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 28 октября 2018

Я согласен, что это плохая идея, и надеюсь, что вы действительно знаете, что делаете.Правильная обработка исключений - моя любимая мозоль, и твоя идея не звучит твердо.Вот две статьи по этому вопросу, которые я считаю обязательными для прочтения и ссылки:

https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/

https://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET

При всем этом у кого-то однажды возникла проблемачто он не мог использовать TryParse, потому что он работал на .NET 1.1.Поэтому я быстро связал эту альтернативу tryParse вместе:

//Parse throws ArgumentNull, Format and Overflow Exceptions.
//And they only have Exception as base class in common, but identical handling code (output = 0 and return false).

bool TryParse(string input, out int output){
  try{
    output = int.Parse(input);
  }
  catch (Exception ex){
    if(ex is ArgumentNullException ||
      ex is FormatException ||
      ex is OverflowException){
      //these are the exceptions I am looking for. I will do my thing.
      output = 0;
      return false;
    }
    else{
      //Not the exceptions I expect. Best to just let them go on their way.
      throw;
    }
  }

  //I am pretty sure the Exception replaces the return value in exception case. 
  //So this one will only be returned without any Exceptions, expected or unexpected
  return true;

}

Я думаю, что проблема (очень далеко за исключением исключений с точно такой же обработкой) такая же, как у вас.

0 голосов
/ 28 октября 2018

Хотя я полностью согласен с ответом @ Loofer (+1 за это).

Кажется, у вас другой вариант использования.

Так что дайте ответ на этот вопрос

Кроме того, у меня есть 5 исключений, которые я хочу проверить, означает ли это, что мне нужно 5 различных блоков try / catch или я могу обработать их все в одном блоке?

Выследует использовать блок Multiple Catch

что-то вроде

try
{
    //
}
catch(Type1Exception exception)
{
}
catch(Type2Exception exception)
{
}
catch(Type3Exception exception)
{
}

и т. д.

Но есть и другой способ, который отвечает на оба ваших вопроса.

, что также является личным предложением, и это будет создание одного вспомогательного метода, например,

private void HandleCustomException(Exception exception)
{
    // Your Error Handling Code goes here
    if(exception is Type1Exception)
    {...}
    ...
}

, а затем добавьте отдельную попытку try в события клика, которые будут отправлять все полученные исключения.этот вспомогательный метод

как-то так

private void createButton1_Click(object sender, EventArgs e)
{
    try
    {
        if(Your Condition)
        {
            throw new Type1Exception();
        }
    }
    catch(Exception exception)
    {
        HandleCustomException(exception);
    }
}
0 голосов
/ 28 октября 2018

Извините за ответ «не делай этого» ...

Использование исключений для «нормального» потока управления бизнесом не является хорошей практикой.Исключения должны быть для исключительных событий.

Совершенно очевидно, что люди создают аккаунты со слишком небольшим балансом и (во всяком случае, для меня) пытаются вывести больше средств, чем у них есть в аккаунте.Эти ошибки должны обрабатываться обычными потоками управления (вещи типа (if balance < MIN_BALANCE)).

Более подробное обсуждение см. Здесь https://softwareengineering.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why

. Для дальнейшего продвижения можно исследовать события, возникающие при нарушении бизнес-правил.Есть много способов сделать это ... вот простая вещь, которую вы можете попробовать. Понимание событий и обработчиков событий в C #

...