I am new in c# development. I just trying to study the delegate feature. Based on the articles and notes I read about delegates, I tried to write a sample code to implement delegate based on what I understood from those notes and articles.
But I am getting an error while running the sample
"Object reference not set to an instance of an object."
What is the problem here ?. or Did I implemented the delegate in correct way ? or Is my concept about delegate is wrong ?..
Please help. Thanks in advance.
I posted my code below.
default.aspx.cs
public partial class _Default : System.Web.UI.Page
{
TestClass myObject = new TestClass();
protected void Page_Load(object sender, EventArgs e)
{
myObject.MyDelegateEvent += new TestClass.MyDelegate(myObject_MyDelegateEvent);
}
void myObject_MyDelegateEvent(object sender, EventArgs e)
{
Console.WriteLine("Delegate event called");
}
}
TestClass
public class TestClass
{
public delegate void MyDelegate(object sender, EventArgs e);
public event MyDelegate MyDelegateEvent;
public TestClass()
{
MyDelegateEvent(this, null); // Here getting error "Object reference not set to an instance of an object."
}
}
What you are trying is: raising the event in the constructor itself, i.e. at the time when there is no subscriber for your event hence MyDelegateEvent is null.
Best option is to null check before raising the event
//Check for not null
if(MyDelegateEvent != null)
{
MyDelegateEvent(this, null);
}
Always test for null before raising the event:
if (this.MyDelegateEvent != null)
{
// Raises the event here
}
If no handler is attached to your event when it is raised (which is the case here as it's raised in the constructor), a null reference exception can be thrown.
EDIT:
For the sake of completeness, when no event argument is used, you should use EventArgs.Empty instead of null:
if (this.MyDelegateEvent != null)
{
this.MyDelegateEvent(this, EventArgs.Empty);
}
Also, there is a EventHandler delegate that can be used when you do not specify any event argument. This is useful as you don't have to write your own each time.
When you declare an event, the event is initialised to null. So, in your TestClass constructor you attempt to fire the event but as the event is null this causes the NullReferenceException you are seeing.
To avoid this you need to register an event handler or check for null before raising the event:
if (MyDelegateEvent != null)
{
MyDelegateEvent(...)
}
Another trick is to initialise the event to an empty delegate when you create it which means you can skip the null checks.
public event MyDelegate MyDelegateEvent = delegate {}; // registers a delegate that does nothing
Minor point about some of the code above. It is possible for MyDelegateEvent to be changed between being checked and used. The recommended form (Framework Design Guidelines) is along the lines of
var del = MyDelegateEvent;
if (del != null) {
del(...);
}
hth,
Alan.
Related
I have a data structure class that is a child of a larger data/state class.
The inner data structure fires an event when the contained data changes. This event is consumed by the larger data/state class. The data/state class then fires its own event so that it may pass additional information along to the next event handler.
Public class Data
{
//properties and objects go here
public int Count
{
get { return _count; }
internal set
{
//if the count grew simply set _count
if (value != _oldCount)
{
_oldCount = _count;
_count = value;
}
//if the count shrank then set the count and trigger an event if the count is under 100
else
{
_oldCount = _count;
_count = value;
if (_count < 100)
{
CountChanged(this, new EventArgs());
}
}
}
}
public event EventHandler CountChanged;
}
The above event is consumed by this event handler
Data.CountChanged += new EventHandler(DataCountChanged);
private void DataCountChanged(object sender, EventArgs e)
{
DataRemoved(this, e); //Handle the old event and trigger a new event to pass along more information
}
public event EventHandler DataRemoved;
Finally the second event should be handled by another event handler to do some work. Unfortunately the call to trigger the second event fails with a NullReferenceException more often than not. Why?
----EDIT----
I understand that checking for Null will prevent the exception. The confusion is why this event is Null in the first place =D
You should always raise events using the following pattern to avoid null references and threading issues:
private void DataCountChanged(object sender, EventArgs e)
{
var dr = DataRemoved;
if (dr != null)
{
dr(this, e);
}
}
The reason the handler is null is that it should be viewed as a special collection of delegates. When the collection is empty the delegate has a null value. When you attach one or more handlers the collection is no longer empty and thus is no longer null.
if(DataRemoved != null && DataRemoved.GetInvocationList().Length > 0)
{
}
Assigning an empty delegate to your events may not be such a good design practice. Events are essentially delegates which are like function pointers. In other words, they are just like other reference members in your class. Unless you assign them a value or subscribe to them, they will be and should be null.
The null reference exception you get is for the same reason as declaring private MyClass; and then trying to use it before it has been assigned a value.
When you subscribe to an event, you are essentially telling the event which function to call. If your event does not have at least one such function pointer, it would not be in existence (NULL).
There is a trick to avoid the null check:
Just initialize your event as follows:
public event YourDelegate MyEvent = delegate { };
This way you do not need to check for nulls just call the event as usual:
this.MyEvent("Hi there!");
Edited
To clarify:
Declaring an event like this:
public event Action MyEvent;
It's translated automatically to:
private Action myEvent;
public event Action MyEvent
{
add
{
this.myEvent += value;
}
remove
{
this.myEvent -= value;
}
}
Therefore initializing an event like this:
public event Action MyEvent = delegate { };
It's safe because external code can not assign a null to the event itself.
You can however, assign null to the event inside the class it was declares but what really is happening is that, you are assigning null to the private delegate used by the event.
Source: Jon Skeet, C# In Depth, Events
I looked at this example from the C# in nutshell book
(http://www.albahari.com/nutshell/ch04.aspx)
using System;
public class PriceChangedEventArgs : EventArgs
{
public readonly decimal LastPrice;
public readonly decimal NewPrice;
public PriceChangedEventArgs (decimal lastPrice, decimal newPrice)
{
LastPrice = lastPrice; NewPrice = newPrice;
}
}
public class Stock
{
string symbol;
decimal price;
public Stock (string symbol) {this.symbol = symbol;}
public event EventHandler<PriceChangedEventArgs> PriceChanged;
****protected virtual void OnPriceChanged (PriceChangedEventArgs e)
{
if (PriceChanged != null) PriceChanged (this, e);
}****
public decimal Price
{
get { return price; }
set
{
if (price == value) return;
OnPriceChanged (new PriceChangedEventArgs (price, value));
price = value;
}
}
}
class Test
{
static void Main()
{
Stock stock = new Stock ("THPW");
stock.Price = 27.10M;
// register with the PriceChanged event
stock.PriceChanged += stock_PriceChanged;
stock.Price = 31.59M;
}
static void stock_PriceChanged (object sender, PriceChangedEventArgs e)
{
if ((e.NewPrice - e.LastPrice) / e.LastPrice > 0.1M)
Console.WriteLine ("Alert, 10% stock price increase!");
}
}
What I don't understand, is why this convention is used...
****protected virtual void OnPriceChanged (PriceChangedEventArgs e)
{
if (PriceChanged != null) PriceChanged (this, e);
}****
Why do I need that method and why do I care to give it the "this" parameter?!? Cant I just attach the event from that class with the method PriceChanged in the test class straight away and skip that method?!?
You need the null check, since an event will be null until somebody subscribes to it. If you raise it directly and it's null, an exception will be thrown.
This method is used to raise the event, not to subscribe to it. You can subscribe to the event from another class easily:
yourObject.PriceChanged += someMethodWithTheAppropriateSignature;
However, when you want to have the event "fire", the class needs to raise the event.
The "this" parameter is providing the sender argument in the EventHandler<T>. By convention, delegates used for events have two parameters, the first is object sender, which should be the object that raised the event. The second is EventArgs or a subclass of EventArgs, which provides the information specific to that event. The method is used to properly check for null and raise the event with the appropriate information.
In this case, your event is declared as:
public event EventHandler<PriceChangedEventArgs> PriceChanged;
EventHandler<PriceChangedEventArgs> is a delegate which has a signature of:
public delegate void EventHandler<T>(object sender, T args) where T : EventArgs
This means that the event must be raised with two parameters - an object (the sender, or "this"), and an instance of PriceChangedEventArgs.
That being said, this convention is not actually the "best" way to raise the event. It would actually be better to use:
protected virtual void OnPriceChanged (PriceChangedEventArgs e)
{
var eventHandler = this.PriceChanged;
if (eventHandler != null)
eventHandler(this, e);
}
This protects you in multi-threaded scenarios, since it's possible that a single subscribe could actually unsubscribe in between your null check and the raise if you have multiple threads operating.
This is a convenience for invoking the event.
You do need to check that the event has subscribers, and it is typical to pass this as the sender of the event.
Because the same handler can be used for multiple events, passing an instance of the sender is the only way that you could reliable unsubscribe from the event once it has fired.
I think the preferred way to invoke is to assign to a variable first, lest PriceChanged become null after checking, but before invoking:
var handler = PriceChanged;
if(handler != null) handler(this, e);
Null checks are used since a (event) delegate list is not empty but null if there are no subscribers.
However, it's not thread safe. So it can blow up in your face if you start using a BackgroundWorker or any other multi-threaded technique.
I suggest that you use an empty delegate instead:
public event EventHandler<PriceChangedEventArgs> PriceChanged = delegate {};
Since it allows you to just write:
protected virtual void OnPriceChanged (PriceChangedEventArgs e)
{
PriceChanged (this, e);
}
It's thread safe and the code is more easy to read.
why do I care to give it the "this" parameter?!?
Same event handler might be used by multiple event generators. The sender tells which generate the invocation is for. You should always send the correct event generator as it is expected and you'll break open/closed principle if you don't
Why Do I need that method?
You don't, unless you would duplicate code otherwise (such as generating the EventArgs class)
I have a UserControl which contains 3 labels. I want to add an event for it, which occurs when the text of one of the labels changed.
I am using Visual Studio 2010
First, you need to declare the event within your class (alongside your methods and constructors):
public event EventHandler LabelsTextChanged;
Then you need to create a method to handle the individual labels' TextChanged events.
private void HandleLabelTextChanged(object sender, EventArgs e)
{
// we'll explain this in a minute
this.OnLabelsTextChanged(EventArgs.Empty);
}
Somewhere, probably in your control's constructor, you need to subscribe to the label's TextChanged events.
myLabel1.TextChanged += this.HandleLabelTextChanged;
myLabel2.TextChanged += this.HandleLabelTextChanged;
myLabel3.TextChanged += this.HandleLabelTextChanged;
Now for the HandleLabelsTextChanged method. We could raise LabelsTextChanged directly; however, the .NET framework design guidelines say that is it a best practice to create an OnEventName protected virtual method to raise the event for us. That way, inheriting classes can "handle" the event by overriding the OnEventName method, which turns out to have a little better performance than subscribing to the event. Even if you think you will never override the OnEventName method, it is a good idea to get in the habit of doing it anyway, as it simplifies the event raising process.
Here's our OnLabelsTextChanged:
protected virtual void OnLabelsTextChanged(EventArgs e)
{
EventHandler handler = this.LabelsTextChanged;
if (handler != null)
{
handler(this, e);
}
}
We have to check for null because an event without subscribers is null. If we attempted to raise a null event, we would get a NullReferenceException. Note that we copy the event's EventHandler to a local variable before checking it for null and raising the event. If we had instead done it like this:
if (this.LabelsTextChanged != null)
{
this.LabelsTextChanged(this, e);
}
We would have a race condition between the nullity check and the event raising. If it just so happened that the subscribers to the event unsubscribed themselves just before we raised the event but after we checked for null, an exception would be thrown. You won't normally encounter this issue, but it is best to get in the habit of writing it the safe way.
Edit: Here is how the public event EventHandler LabelsTextChanged; line should be placed:
namespace YourNamespace
{
class MyUserControl : UserControl
{
// it needs to be here:
public event EventHandler LabelsTextChanged;
...
}
}
Here are the framework design guidelines on event design for further reading.
First you should declare an event in your usercontrol for example:
public event EventHandler TextOfLabelChanged;
then you have to call the call back function that is bound to your event(if there's any) in runtime.You can do this by handling the TextChanged event of a label like this:
public void LabelTextChanged(object sender,EventArgs e)
{
if(TextOfLabelChanged!=null)
TextOfLabelChanged(sender,e);
}
You can have your own EventArgs object if you like.
somewhere in your code you should bound your label TextChanged event to this method like this:
_myLabel.TextChanged+=LabelTextChanged;
public delegate void TextChangedEventHandler(object sender, EventArgs e);
public event TextChangedEventHandler LabelTextChanged;
// ...
protected void MyTextBox_TextChanged(object sender, EventArgs e)
{
if (LabelTextChanged != null) {
LabelTextChanged(this, e);
}
}
compile error, which says: "Expected class, delegate, enum, interface, or struct" on the second line it seems to have a problem with "event...
These 2 lines need to be INSIDE the class declaration.
public delegate void TextChangedEventHandler(object sender, EventArgs e);
public event TextChangedEventHandler LabelTextChanged;
There is a very simple way to do that!
On the UserControl Form :
change properties to public to access everywhere
on the main form , where you are using UserControl:
.5: in the using region add using userControl1=UserControl.userControl1
1.Add 'Laod' event to your UserControl :
this.userControl1.Load += new System.EventHandler(this.userControl1_Load);
2.In the userControl1_Load :
private void userControl1_Load(object sender, EventArgs e)
{
(sender as UserControl1).label1.TextChanged += label1_TextChanged;
//add a 'TextChanged' event to the label1 of UserControl1
OR use direct cast:
((UserControl1) sender).label1.TextChanged += label1_TextChanged;
}
3.In th label1_TextChanged:
private void label1_TextChanged(object sender, EventArgs e)
{
//do whatever you want
}
You must be declaring the event and delegate within the Namespace. Try to bring the code within the class Scope. It will run fine.
I'm a beginner in C# and having hard times understanding Events in C# .. The book i read (Illustrated C# 2008) gives an example about it , and there are few thing i need to ask about , so i will past the code here and point out the things i don't understand .
public class MyTimerClass
{
public event EventHandler Elapsed;
private void OnOneSecond(object source, EventArgs args)
{
if (Elapsed != null)
Elapsed(source, args);
}
}
class ClassA
{
public void TimerHandlerA(object obj, EventArgs e) // Event handler
{
Console.WriteLine("Class A handler called");
}
}
class ClassB
{
public static void TimerHandlerB(object obj, EventArgs e) // Static
{
Console.WriteLine("Class B handler called");
}
}
class Program
{
static void Main( )
{
ClassA ca = new ClassA(); // Create the class object.
MyTimerClass mc = new MyTimerClass(); // Create the timer object.
mc.Elapsed += ca.TimerHandlerA; // Add handler A -- instance.
mc.Elapsed += ClassB.TimerHandlerB; // Add handler B -- static.
Thread.Sleep(2250);
}
}
Ok, now the line after declaring the event here public event EventHandler Elapsed;
which is private void OnOneSecond(object source, EventArgs args) i know that the two line after it is to check if the event contains methods or not , but what is OnOneSecound for ? or when it's called ? or what it's named .. it's not event handler i guess right ? and what's the relationship between Elapsed and OnOneSecond ?
sorry for the newbie question .. and thanks in advance :)
the OnOneSecond method will be called internally by the MyTimerClass when it needs to invoke the event.
This is a common pattern used by most controls, including the microsoft ones.
Basically you dont need to be checking if the event is set in multiple places, you just do it in this one method then call this method internally to raise the event.
I tend not to pass the event args to the OnXXX method though, for example.
public event EventHandler<EventArgs> SomeEvent;
protected virtual void OnSomeEvent()
{
if (this.SomeEvent !=null)
{
this.SomeEvent.Invoke(this,EventArgs.Empty);
}
}
then to raise it
this.OnSomeEvent();
This is the method, that you call to raise the event safely.
the problem is, you can basically call
Elapsed(source, args)
but if there is noone connected to the event, this will raise a Reference Null exception. as the event is null, when nobody hears on it.
a better solution is, that you directly add a subscriber to the events. then you can safely call it directly. as there will be allways a subscriber.
public event Action<EventArgs> Elapsed = val => { };
(note that with the = its directly assigned. val => { } is a Lambda expression, that defines a empty subscriber.)
Also, look into the Reactive Framework for .net
if you want to do a lot of event stuff, this is the correct solution for it.
That allows you to manually fire the events from thein the class.
That is the standard pattern for raising internal events that's why it is private.
OnOneSecond is just a helper method defined to raise the event. You can use events without such methods, it is just an established pattern to wrap the if (Elapsed != null) check in a method with a name that starts with On...
Technically you could just use Elapsed(source, args) instead of OnOneSecond(source, args), but this will throw NullReferenceException if there are no listeners registered.
Some text before the code so that the question summary isn't mangled.
class Tree
{
public event EventHandler MadeSound;
public void Fall() { MadeSound(this, new EventArgs()); }
static void Main(string[] args)
{
Tree oaky = new Tree();
oaky.Fall();
}
}
I haven't used events much in C#, but the fact that this would cause a NullRefEx seems weird. The EventHandler reference is considered null because it currently has no subsribers - but that doesn't mean that the event hasn't occurred, does it?
EventHandlers are differentiated from standard delegates by the event keyword. Why didn't the language designers set them up to fire silently in to the void when they have no subscribers? (I gather you can do this manually by explicitly adding an empty delegate).
Well, the canonical form is:
void OnMadeSound()
{
if (MadeSound != null)
{
MadeSound(this, new EventArgs());
}
}
public void Fall() { OnMadeSound(); }
which is very slightly faster that calling an empty delegate, so speed won out over programming convenience.
Another good way I've seen to get around this, without having to remember to check for null:
class Tree
{
public event EventHandler MadeSound = delegate {};
public void Fall() { MadeSound(this, new EventArgs()); }
static void Main(string[] args)
{
Tree oaky = new Tree();
oaky.Fall();
}
}
Note the anonymous delegate - probably a slight performance hit, so you have to figure out which method (check for null, or empty delegate) works best in your situation.
The recommended pattern is (.net 2.0+)
public class MyClass
{
public event EventHandler<EventArgs> MyEvent; // the event
// protected to allow subclasses to override what happens when event raised.
protected virtual void OnMyEvent(object sender, EventArgs e)
{
// prevent race condition by copying reference locally
EventHandler<EventArgs> localHandler = MyEvent;
if (localHandler != null)
{
localHandler(sender, e);
}
}
public void SomethingThatGeneratesEvent()
{
OnMyEvent(this, EventArgs.Empty);
}
}
I see a lot of recommendations for an empty delegate{} in an initializer, but I totally disagree with it. If you follow the above pattern you only check the event != null in one place. The empty delegate{} initializer is a waste because it's an extra call per event, it wastes memory, and it still can fail if MyEvent was set to null elsewhere in my class.
* If your class is sealed, you wouldn't make OnMyEvent() virtual.
You need to understand what your event declaration is actually doing. It's declaring both an event and a variable, When you refer to it within the class, you're just referring to the variable, which will be null when there are no subscribers.
Very Zen, eh?
You have to test for null when you want to raise an event:
protected void OnMyEvent()
{
if (this.MyEvent != null) this.MyEvent(this, EventArgs.Empty);
}
It would be nice if you didn't have to bother with this, but them's the breaks.
James provided a good technical reasoning, I would also like to add that I have seen people use this an advantage, if no subscribers are listening to an event, they will take action to log it in the code or something similar. A simpl example, but fitting in this context.
What is the point of raising an event if no one is listening? Technically, its just how C# chose to implement it.
In C#, an event is a delegate with some special feathers. A delegate in this case can be viewed as a linked list of function pointers (to handler methods of subscribers). When you 'fire the event' each function pointer is invoked in turn. Initially the delegate is a null object like anything else. When you do a += for the first subscribe action, Delegate.Combine is called which instantiates the list. (Calling null.Invoke() throws the null exception - when the event is fired.)
If you still feel that "it must not be", use a helper class EventsHelper as mentioned here with old and improved 'defensive event publishing' http://weblogs.asp.net/rosherove/articles/DefensiveEventPublishing.aspx
Using an extension method would be helpful in this scenario.
public static class EventExtension
{
public static void RaiseEvent<T>(this EventHandler<T> handler, object obj, T args) where T : EventArgs
{
if (handler != null)
{
handler(obj, args);
}
}
}
It can then be used like below.
public event EventHandler<YourEventArgs> YourEvent;
...
YourEvent.RaiseEvent(this, new YourEventArgs());
Thank you for the responses. I do understand why the NullReferenceException happens and how to get around it.
Gishu said
What is the point of raising an event if no one is listening?
Well, maybe it's a terminology thing. The appeal of an "event" system seems to me that all the responsibility of the fallout of the event that took place should be on the watchers and not the performer.
Perhaps a better thing to ask is: If a delegate field is declared with the event keyword in front of it, why doesn't the compiler translate all instances of:
MadeSound(this, EventArgs.Empty)
to
if (MadeSound != null) { MadeSound(this, EventArgs.Empty); }
behind the scenes in the same manner that other syntax shortcuts are? The number of boilerplate OnSomeEvent null checking methods that people have to write manually must be colossal.