2016-03-24 2 views
0

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

Эти фрагменты кода находятся в форме платежа, которая обрабатывает конец транзакции. Я объявил 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 }); 

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

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

+3

Вы уверены, что у вас есть подписчики на ваше мероприятие? –

+1

'PaymentForm_PaymentMade'' 'null, если никто не подписал это событие. BTW: «похоже, идет из этой строки», это не лучший способ спросить о StackOverflow! В исключении всегда есть трассировка стека, которая сообщает _exactly_, где происходит ошибка. Включите эту трассировку стека в следующем вопросе. –

+1

@ DanielAWhite - Насколько я обожаю этот обман, его немного суровый в этом случае, поскольку это немного частный случай NRE – Jamiec

ответ

0

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

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 }); 
} 
+0

Просто для полноты, как правило, считается чтобы сохранить событие в локальной переменной перед проверкой/вызовом, чтобы предотвратить проблемы с потоками. Например: 'PaymentMadeEvent LocalEvent = PaymentForm_PaymentMade; if (LocalEvent! = null) ... ' –

+1

@GlorinOakenfoot для полной полноты: этот шаблон фактически устарел с C# 6, так как теперь вы можете сделать' PaymentForm_PaymentMade? .Invoke (...) ' –

+0

@ RenéVogt - Хорошая точка , –