c# starter l06-delegates, event handling and extension methods
DESCRIPTION
C# Starter L06-Delegates, Event Handling and Extension MethodsTRANSCRIPT
Mohammad Shakermohammadshaker.com
C# Programming Course@ZGTRShaker
2011, 2012, 2013, 2014
C# StarterL06 – Delegates, Event Handling and Extension Methods
Delegates
DelegatesHave you ever thought to pass a function as a parameter?
Delegates
• Delegate
– A delegate is an object that points to a function
– is basically a function pointer, C++!
– "Why do I need a reference to a method?"
• The answer boils down to giving you maximum flexibility to implement any functionality you want at
runtime.
– You can use delegate to pass a function as a parameter
Delegate Example
public class MagicNumber{
public int Number { get; set; }}
public void Increment(MagicNumber magicNumber){
magicNumber.Number++;}
public void Decrement(MagicNumber magicNumber){
magicNumber.Number--;}
public delegate void MagicNumberModifier (MagicNumber magicNumber);
Delegate Declaration
Delegate Example
• Now let’s make a list of MagicNumbers
• And a member like this:
List<MagicNumber> magicNumbers = new List<MagicNumber>();
magicNumbers.Add(new MagicNumber() { Number = 4});magicNumbers.Add(new MagicNumber() { Number = 6});magicNumbers.Add(new MagicNumber() { Number = 9});magicNumbers.Add(new MagicNumber() { Number = 13});magicNumbers.Add(new MagicNumber() { Number = 20});
public static void ApplyModifierToAll(MagicNumberModifier modifier, List<MagicNumber> magicNumbers){
foreach(MagicNumber number in magicNumbers){
modifier(number);}
}
Delegate!
public delegate void MagicNumberModifier (MagicNumber magicNumber);
Delegate Example
• Lastly, just call the delegate and let the magic happens
public static void Main(string[] args){
List<MagicNumber> magicNumbers = new List<MagicNumber>();
magicNumbers.Add(new MagicNumber() { Number = 4, IsMagic = true });magicNumbers.Add(new MagicNumber() { Number = 6, IsMagic = false });magicNumbers.Add(new MagicNumber() { Number = 9, IsMagic = true });magicNumbers.Add(new MagicNumber() { Number = 13, IsMagic = false });magicNumbers.Add(new MagicNumber() { Number = 20, IsMagic = true });
ApplyModifierToAll(Increment, magicNumbers);ApplyModifierToAll(Magicify, magicNumbers);
}
MultiCasting-Delegates
• Note!
– If you chain delegates that return values, you may run into some problems. The way C#
handles that situation is by returning the value of only the last function inside the delegate. All
other return values are discarded. So don’t return things that are absolutely vital to your
program if you know the function is going inside a chained delegate.
Event Handling
Event HandlingDelegates and Event Handling
Event HandlingRaise Events when Needed
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
The event handler
Raising the event
Attaching and Detaching Events
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
class Program{
public static void Main(){
new Program().Test();}
private void Test(){
Point point = new Point();
// Here's the real important line:point.PointChanged += HandlePointChanged;
// Now if we change the point, the PointChanged event will get raised,// and HandlePointChanged will get called.point.X = 3;
}
public void HandlePointChanged(object sender, EventArgs eventArgs){
// Do something intelligent when the point changes. Perhaps redraw the GUI,// or update another data structure, or anything else you can think of.
}}
Event HandlingHow it works now..
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
class Program{
public static void Main(){
new Program().Test();}
private void Test(){
Point point = new Point();
// Here's the real important line:point.PointChanged += HandlePointChanged;
// Now if we change the point, the PointChanged event will get raised,// and HandlePointChanged will get called.point.X = 3;
}
public void HandlePointChanged(object sender, EventArgs eventArgs){
// Do something intelligent when the point changes. Perhaps redraw the GUI,// or update another data structure, or anything else you can think of.
}}
When a point is Set the method OnPointChangedwill be called
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
class Program{
public static void Main(){
new Program().Test();}
private void Test(){
Point point = new Point();
// Here's the real important line:point.PointChanged += HandlePointChanged;
// Now if we change the point, the PointChanged event will get raised,// and HandlePointChanged will get called.point.X = 3;
}
public void HandlePointChanged(object sender, EventArgs eventArgs){
// Do something intelligent when the point changes. Perhaps redraw the GUI,// or update another data structure, or anything else you can think of.
}}
Which will consequently raise the event by calling it (checking if the delegate is null for the first time)
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
class Program{
public static void Main(){
new Program().Test();}
private void Test(){
Point point = new Point();
// Here's the real important line:point.PointChanged += HandlePointChanged;
// Now if we change the point, the PointChanged event will get raised,// and HandlePointChanged will get called.point.X = 3;
}
public void HandlePointChanged(object sender, EventArgs eventArgs){
// Do something intelligent when the point changes. Perhaps redraw the GUI,// or update another data structure, or anything else you can think of.
}}
And consequently, calling the delegate that points to the programmer function
public class Point{
private double x;private double y;
public double X{
get{
return x;}set{
x = value;OnPointChanged();
}}
public double Y{
get{
return y;}set{
y = value;OnPointChanged();
}}
public event EventHandler PointChanged;
public void OnPointChanged(){
if(PointChanged != null){
PointChanged(this, EventArgs.Empty);}
}}
class Program{
public static void Main(){
new Program().Test();}
private void Test(){
Point point = new Point();
// Here's the real important line:point.PointChanged += HandlePointChanged;
// Now if we change the point, the PointChanged event will get raised,// and HandlePointChanged will get called.point.X = 3;
}
public void HandlePointChanged(object sender, EventArgs eventArgs){
// Do something intelligent when the point changes. Perhaps redraw the GUI,// or update another data structure, or anything else you can think of.
}}
And consequently, calling the delegate that points to the programmer function
Attaching/Detaching Multiple Events
• The event can easily be removed/changed/added at runtime by -= or +=
• An event can also add multiple function pointers (delegates at the same time),
pointing at all of them at the same time and calling all of them when the event is
raised!
point.PointChanged -= HandlePointChanged;
point.PointChanged += HandlePointChanged;point.PointChanged += HandlePotatoPositionChange;
Anonymous Methods
Anonymous Methods
• An anonymous method is a method without a name
– which is why it is called anonymous.
• You don't declare anonymous methods like regular methods.
– Instead they get hooked up directly to events.
Anonymous Methods
using System.Windows.Forms;
public partial class Form1 : Form{
public Form1(){
Button buttonHello = new Button();buttonHello.Text = "Hello";
buttonHello.Click +=delegate{
MessageBox.Show("Hello");};
Controls.Add(buttonHello);}
}
Anonymous Methods
using System.Windows.Forms;
public partial class Form1 : Form{
public Form1(){
Button buttonHello = new Button();buttonHello.Text = "Hello";
buttonHello.Click +=delegate{
MessageBox.Show("Hello");};
Controls.Add(buttonHello);}
}
Anonymous Methods
public partial class Form1 : Form{
public Form1(){
Button buttonHello = new Button();buttonHello.Text = "Hello";
buttonHello.Click +=delegate{
MessageBox.Show("Hello");};
Button btnGoodBye = new Button();btnGoodBye.Text = "Goodbye";btnGoodBye.Left = buttonHello.Width + 5;
btnGoodBye.Click +=delegate(object sender, EventArgs e){
string message = (sender as Button).Text;MessageBox.Show(message);
};
Controls.Add(buttonHello);Controls.Add(btnGoodBye);
}}
Anonymous Methods
public partial class Form1 : Form{
public Form1(){
Button buttonHello = new Button();buttonHello.Text = "Hello";
buttonHello.Click +=delegate{
MessageBox.Show("Hello");};
Button btnGoodBye = new Button();btnGoodBye.Text = "Goodbye";btnGoodBye.Left = buttonHello.Width + 5;
btnGoodBye.Click +=delegate(object sender, EventArgs e){
string message = (sender as Button).Text;MessageBox.Show(message);
};
Controls.Add(buttonHello);Controls.Add(btnGoodBye);
}}
Anonymous Methods
public partial class Form1 : Form{
public Form1(){
Button buttonHello = new Button();buttonHello.Text = "Hello";
buttonHello.Click +=delegate{
MessageBox.Show("Hello");};
Button btnGoodBye = new Button();btnGoodBye.Text = "Goodbye";btnGoodBye.Left = buttonHello.Width + 5;
btnGoodBye.Click +=delegate(object sender, EventArgs e){
string message = (sender as Button).Text;MessageBox.Show(message);
};
Controls.Add(buttonHello);Controls.Add(btnGoodBye);
}}
Anonymous Methods
public partial class Form1 : Form{
public Form1(){
Button buttonHello = new Button();buttonHello.Text = "Hello";
buttonHello.Click +=delegate{
MessageBox.Show("Hello");};
Button btnGoodBye = new Button();btnGoodBye.Text = "Goodbye";btnGoodBye.Left = buttonHello.Width + 5;
btnGoodBye.Click +=delegate(object sender, EventArgs e){
string message = (sender as Button).Text;MessageBox.Show(message);
};
Controls.Add(buttonHello);Controls.Add(btnGoodBye);
}}
Anonymous Methods
public partial class Form1 : Form{
public Form1(){
Button buttonHello = new Button();buttonHello.Text = "Hello";
buttonHello.Click +=delegate{
MessageBox.Show("Hello");};
Button btnGoodBye = new Button();btnGoodBye.Text = "Goodbye";btnGoodBye.Left = buttonHello.Width + 5;
btnGoodBye.Click +=delegate(object sender, EventArgs e){
string message = (sender as Button).Text;MessageBox.Show(message);
};
Controls.Add(buttonHello);Controls.Add(btnGoodBye);
}}
Extension Methods
Extension MethodsExtension methods are a way to create a method that feels like it is part of a specific class
(like, the string class) when you don't actually have access to that class to modify, and add the method.
Extension MethodsIt’s a way to add functionalities to classes you don’t own
Extension MethodsIt’s a way to add functionalities to classes you don’t own
that’s why they are called Extension Methods
Extension Methods
• Extension methods must be added in static classes (where methods in that static
class should also be static)
• Now, Let’s extend the String class with a ToRandomCase method that
randomize the letter cases in a given string.
Extension Methodspublic static class StringExtensions
{private static Random random = new Random();
public static string ToRandomCase(this string text){
string result = "";
for (int index = 0; index < text.Length; index++){
if (random.Next(2) == 0){
result += text.Substring(index, 1).ToUpper();}else{
result += text.Substring(index, 1).ToLower();}
}
return result;}
}
Static class
Extension Methodspublic static class StringExtensions
{private static Random random = new Random();
public static string ToRandomCase(this string text){
string result = "";
for (int index = 0; index < text.Length; index++){
if (random.Next(2) == 0){
result += text.Substring(index, 1).ToUpper();}else{
result += text.Substring(index, 1).ToLower();}
}
return result;}
}
Static data member
Extension Methodspublic static class StringExtensions
{private static Random random = new Random();
public static string ToRandomCase(this string text){
string result = "";
for (int index = 0; index < text.Length; index++){
if (random.Next(2) == 0){
result += text.Substring(index, 1).ToUpper();}else{
result += text.Substring(index, 1).ToLower();}
}
return result;}
}
Static method
Extension Methodspublic static class StringExtensions
{private static Random random = new Random();
public static string ToRandomCase(this string text){
string result = "";
for (int index = 0; index < text.Length; index++){
if (random.Next(2) == 0){
result += text.Substring(index, 1).ToUpper();}else{
result += text.Substring(index, 1).ToLower();}
}
return result;}
}
The extended class (string)
with the this keyword
Extension Methodspublic static class StringExtensions
{private static Random random = new Random();
public static string ToRandomCase(this string text){
string result = "";
for (int index = 0; index < text.Length; index++){
if (random.Next(2) == 0){
result += text.Substring(index, 1).ToUpper();}else{
result += text.Substring(index, 1).ToLower();}
}
return result;}
}
A simple randomization
algorithm
Extension Methods
• Now just call the method!
public static void Main(){
string message = "Do you wish me a good morning, or mean that it is a good morning whether I want it or not; or that you feel good this morning; or that it is a morning to be good on?";
Console.WriteLine(message.ToRandomCase());}
Do You WisH mE A gOOD MOrniNG, Or mEan that it iS a GOOD moRnIng wHether i Want It or noT; Or that yOufeeL goOD THiS morning; OR tHaT it iS A MOrNINg to be GoOd On?Press any key to continue . . .