c # Пустая ссылка, вызывающая проблемы для пользовательских EventArgs

Я создаю систему EPoS для университетского проекта, но я столкнулся с кирпичной стеной с фрагментом сложного кода, касающегося аргументов событий.

Эти фрагменты кода находятся в платежной форме, которая обрабатывает завершение транзакции. Я объявил PaymentMadeEvent так:

    public delegate void PaymentMadeEvent(object sender, paymentMadeEventArgs e);

    public event PaymentMadeEvent PaymentForm_PaymentMade;

Затем я объявил логическое значение в отдельном общедоступном классе внизу кодовой страницы следующим образом:

public class paymentMadeEventArgs: EventArgs
{
    private bool paymentSuccess = true;

    public bool PaymentSuccess
    {
        get { return paymentSuccess; }
        set { paymentSuccess = value; }
    }
}

Затем я скопировал пример кода, который обрабатывает платеж при его вводе:

private void PaymentHasBeenMade(object sender, EventArgs e)
    {

        try
        {
            total = decimal.Parse(txtBoxAmountToPay.Text) - decimal.Parse(txtBoxAmountTendered.Text);
        }
        catch
        {
            MessageBox.Show("An Error has occured, please enter a valid amount.");
            return;
        }

        if(total >0)
        {
            txtBoxAmountToPay.Text = String.Format("{0:c}", total);
        }
        else
        {
            MessageBox.Show("Please give " + String.Format("{0:c}", -total) + " in change.");
            PaymentForm_PaymentMade(this, new paymentMadeEventArgs(){ PaymentSuccess = true });
        }
    }

Ошибка

System.NullReferenceException

который, кажется, исходит из этой строки здесь:

PaymentForm_PaymentMade(this, new paymentMadeEventArgs(){ PaymentSuccess = true });

Может ли кто-нибудь увидеть, что я делаю неправильно?

Заранее спасибо.


person Tom Allen    schedule 24.03.2016    source источник
comment
Вы уверены, что у вас есть подписчики на ваше мероприятие?   -  person Glorin Oakenfoot    schedule 24.03.2016
comment
PaymentForm_PaymentMade равно null, если никто не подписался на это событие. Кстати: кажется, что эта строка исходит из этой строки, это не лучший способ спросить в StackOverflow! Исключение всегда имеет трассировку стека, которая сообщает вам точно, где возникает ошибка. Пожалуйста, включите эту трассировку стека в свой следующий вопрос.   -  person René Vogt    schedule 24.03.2016
comment
@DanielAWhite - Как бы мне ни нравился этот обман, в данном случае он немного суров, так как это особый случай NRE.   -  person Jamiec    schedule 24.03.2016
comment
Даниэль, есть ли шанс связать меня с указанным вопросом? Я пытался найти час в течение почти 4 часов и пришел с пустыми руками. Glorin, у меня на форме есть четыре кнопки, которые используют это событие.   -  person Tom Allen    schedule 24.03.2016
comment
stackoverflow.com/questions/24640994/, возможно, был бы лучшим дубликатом   -  person Jamiec    schedule 24.03.2016


Ответы (1)


События нулевые, пока у них нет подписчиков, поэтому вам нужно

if(PaymentForm_PaymentMade != null)
    PaymentForm_PaymentMade(this,new paymentMadeEventArgs(){ PaymentSuccess = true })

Это происхождение определенного шаблона кода, который начинается с того, что имя вашей формы не повторяется в имени события:

public event PaymentMadeEvent PaymentMade;

И имея метод On<EventName>, обычно защищенный.

protected void OnPaymentMade(PaymentMadeEventArgs e)
{
    if(this.PaymentMade != null)
         this.PaymentMade(this,e);
}

Тогда вам не придется пачкать весь код if(...)

if(total >0)
{
    txtBoxAmountToPay.Text = String.Format("{0:c}", total);
}
else
{
    MessageBox.Show("Please give " + String.Format("{0:c}", -total) + " in change.");
    OnPaymentMade(new PaymentMadeEventArgs(){ PaymentSuccess = true });
}
person Jamiec    schedule 24.03.2016
comment
Просто для полноты обычно считается правильным сохранить событие в локальной переменной перед проверкой/вызовом, чтобы предотвратить проблемы с потоками. Например: PaymentMadeEvent LocalEvent = PaymentForm_PaymentMade; if(LocalEvent != null) ... - person Glorin Oakenfoot; 24.03.2016
comment
@GlorinOakenfoot для полной полноты: этот шаблон фактически устарел с C # 6, поскольку теперь вы можете делать PaymentForm_PaymentMade?.Invoke(...) - person René Vogt; 24.03.2016
comment
@RenéVogt - Хороший вопрос. - person Glorin Oakenfoot; 24.03.2016