Most of the time when we use MVVM we use the INotifyPropertyChanged interface to provide the notification to the bindings, and the general implementation looks like this:
public class MyClass : INotifyPropertyChanged
{
// properties implementation with RaisePropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
This works fine for me whenever I read the code from the experts - they wrote similar code:
public class MyClass : INotifyPropertyChanged
{
// properties implementation with RaisePropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
var tempchanged = PropertyChanged;
if (tempchanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I would like to know what is the exact reason behind creating a temporary object for the PropertyChanged event.
Is it only a good practice or are there any other benefits associated with it?
I have found the answer with Jon's answer and the explained example at:
Understanding C#: Raising events using a temporary variable
Here is the sample code to understand this:
using System;
using System.Collections.Generic;
using System.Threading;
class Plane
{
public event EventHandler Land;
protected void OnLand()
{
if (null != Land)
{
Land(this, null);
}
}
public void LandThePlane()
{
OnLand();
}
}
class Program
{
static void Main(string[] args)
{
Plane p = new Plane();
ParameterizedThreadStart start = new ParameterizedThreadStart(Run);
Thread thread = new Thread(start);
thread.Start(p);
while (true)
{
p.LandThePlane();
}
}
static void Run(object o)
{
Plane p = o as Plane;
while (p != null)
{
p.Land += p_Land;
p.Land -= p_Land;
}
}
static void p_Land(object sender, EventArgs e)
{
return;
}
}
Use the Shared modifier to create a shared event if you need to raise an event from a constructor. You can change the default behavior of events by defining a custom event. For custom events, the RaiseEvent statement invokes the event's RaiseEvent accessor.
Typically, to raise an event, you add a method that is marked as protected and virtual (in C#) or Protected and Overridable (in Visual Basic). Name this method On EventName; for example, OnDataReceived .
To subscribe to events by using the Visual Studio IDEOn top of the Properties window, click the Events icon. Double-click the event that you want to create, for example the Load event. Visual C# creates an empty event handler method and adds it to your code. Alternatively you can add the code manually in Code view.
When testing that a class raises events correctly, there are three elements to verify. Firstly, the class should raise the correct event according to the process being executed. Secondly, the event should refer to the object that raised it.
You're not creating a temporary object. You're using a local variable to avoid a race condition.
In this code:
if (PropertyChanged != null)
{
PropertyChanged(...);
}
it's possible for PropertyChanged
to become null
(due to the last subscriber unsubscribing) after the nullity check, which will mean you get a NullReferenceException
.
When you use a local variable, you ensure that the reference you check for nullity is the same reference that you use to raise the event - so you won't get the exception. There's still a race condition in that you may end up calling subscribers who have just unsubscribed, but that's unavoidable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With