Hello!
> If I insted run the program in debug mode I get a nullReferenceException.
>
> Can somebody explain that?
> Off the top of my head, no. There's nothing in the code you posted that
> would suggest that in any build, release or otherwise, that you should not
> get a null reference exception when trying to invoke the null delegate
> reference.
> If you'd provided a concise-but-complete code sample, perhaps the answer
> would be more apparent.
Here is a complete simple program example which consist of four classes.
There are two things in this example that are relevant for my question and
that is
Timers and delegate.
In this program example there is a Timer object which has a interval set to
1 second. When this
timer has elapse it will call the event handler OnTimedEvent. In this method
handler OnTimedEvent it will call
method Notify. In this method Notify it will call the delegate method that
has been added to the delegate variable
tickers. But if no method has been added do the delegate variable it will be
null. So if I run the program in relese mode and don't add a method to the
delegete variable tickers it will be null but I don't get any
nullReferenceException.
When I test and don't add a mehod to the delegete I just modify the program
and comment out these two lines below
tickers += newMethod; //add method newMethod to delegete
tickers -= oldMethod; //remove method newMethod from delegate
The Timer will still function elapsing every second even if no method has
been added to the delegete variable tickers.
But now to the strange thing if I run the program in debug mode I get a
nullReference Exception.
So as summery why do I get a nullReferenceExcetion in Debug but no in
release. I would be satisfied if I got a nullReferenceException in both
release and debug mode.
First you have the class Program below.
//Start class Program
//***************
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Delegates
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
}
//Start class Form1
//***************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace Delegates
{
partial class Form1 : Form
{
private Clock clock;
public Form1()//C-tor
{
InitializeComponent();
clock = new Clock(digital);
}
private void start_Click(object sender, System.EventArgs e)
{
clock.Start();
}
private void stop_Click(object sender, System.EventArgs e)
{
clock.Stop();
}
}
}
//Start class Clock
//*************
using System.Windows.Forms;
namespace Delegates
{
class Clock
{
private Ticker pulsed = new Ticker();
private TextBox display;
public Clock(TextBox displayBox)//C-tor
{
display = displayBox;
}
public void Start()
{
pulsed.Add(RefreshTime); //Call add to add method
RefreshTime
}
public void Stop()
{
pulsed.Remove(RefreshTime);//call remove to remove method
RefreshTime
}
private void RefreshTime(int hh, int mm, int ss)
{
display.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", hh, mm,
ss);
}
}
}
//Start class Ticker
//*************
namespace Delegates
{
using System.Timers;
class Ticker
{
public delegate void Tick(int hh, int mm, int ss); //delegate
declaration
private Tick tickers; // delegate variable
private Timer ticking = new Timer(); // instansiate Timer
public Ticker() //C-tor
{
ticking.Elapsed += new ElapsedEventHandler(OnTimedEvent); //
eventhandler to be called when timer elapse
ticking.Interval = 1000; // 1 second interval
ticking.Enabled = true;
}
public void Add(Tick newMethod) // delegete type
{
tickers += newMethod; //add method newMethod to delegete
}
public void Remove(Tick oldMethod) //delegete type
{
tickers -= oldMethod; //remove method newMethod from delegate
}
private void Notify(int hours, int minutes, int seconds)
{
tickers(hours, minutes, seconds); //call hidden delegate
method
}
//eventhandler that is called when timer is elapsing
private void OnTimedEvent(object source, ElapsedEventArgs args)
{
int hh = args.SignalTime.Hour;
int mm = args.SignalTime.Minute;
int ss = args.SignalTime.Second;
Notify(hh, mm, ss); // call notify
}
}
}
//Tony
On Sat, 26 Jan 2008 11:11:29 -0800, Tony Johansson
<johansson.andersson@telia.com> wrote:
> [...]
> Now to my question: When the eventhandler Notify is called as a result of
[quoted text clipped - 7 lines]
>
> Can somebody explain that?
Off the top of my head, no. There's nothing in the code you posted that
would suggest that in any build, release or otherwise, that you should not
get a null reference exception when trying to invoke the null delegate
reference.
If you'd provided a concise-but-complete code sample, perhaps the answer
would be more apparent.
> One more thing is it a good idea to check if tickes is null?
Yes, of course. You shouldn't dereference reference type variables until
you know for sure that they are non-null. You can either do this by
always initializing them to some known non-null value, or you can just
check for null before use.
As an example of the former, you could initialize "tickers" like this:
Tick ticker = delegate { };
Otherwise, yes...you should check the variable for null before trying to
invoke it.
Pete
Ben Voigt [C++ MVP] - 28 Jan 2008 19:31 GMT
> Hello!
>
[quoted text clipped - 37 lines]
> release. I would be satisfied if I got a nullReferenceException in both
> release and debug mode.
I imagine that a NullReferenceException is generated and it terminates the
worker thread where the Timer callback is executing, you just didn't get any
message.
> First you have the class Program below.
> //Start class Program
[quoted text clipped - 176 lines]
>
> Pete