Powerpoint exploring the locations used in television show Time Clash
C# Delegates, Events, Lambda
1. C#:
Delegates,
Events
and
Lambda
Jussi
Pohjolainen
Tampere
University
of
Applied
Sciences
2. About
Callbacks
• Callback
methods
can
be
implemented
in
C#
using
delegates,
events
and
lambda
• Callback
method?
– When
buGon
is
clicked,
a
method
is
called
(calls
back
a
method
you
have
implemented)
• Delegate
type
“points”
to
a
method
or
a
list
of
methods
– Event
will
help
you
to
build
callback
mechanism
• Lambda
is
anonymous
method
and
provides
simplified
approach
working
with
delegates
3. JavaScript:
Callback
function doSomething(integer, someFunction) {
var i = 0, s = 0;
for(i = 0; i<integer; i = i + 1) {
s += integer;
}
// callback!
someFunction(s);
}
function callBackFunction(result) {
print('result is: ' + result);
}
function main() {
doSomething(5000, callBackFunction);
}
main();
4. Java
7:
Anonymous
methods
and
callbacks
// Kind of hard?
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do something
}
})
// Note: Java 8 will have lambda
6. Delegate
• Delegate
type
holds
– Address
of
the
method
on
which
it
makes
calls
– Parameters
of
the
method
– Return
type
of
the
method
• Works
both
asynchronously
and
synchronously.
Simplifies
things,
no
need
for
Thread
object.
Let’s
see
this
later
7. Example
// Following delegate type can point to whatever
// method as long as it's returning int and it has two
// parameters.
public delegate int Something(int a, int b);
// This will generate a following class! Lot of methods
// also deriving from MulticastDelegate and Delegate (base class
// for MulticastDelegate)
sealed class Something : System.MulticastDelegate
{
public int Invoke(int x, int y);
public IAsyncResult BeginInvoke(int x, int y, AsyncCallback cb, object state);
public int EndInvoke(IAsyncResult result);
}
8. using System;
public delegate int Something(int a, int b);
class MyMath
{
public int Add(int a, int b)
{
return a + b;
}
}
class MyMain
{
public static void Main() {
MyMath m = new MyMath();
Something delegateObject = new Something(m.Add);
Console.WriteLine( delegateObject.Invoke(5,5) );
// Calls Invoke!
Console.WriteLine( delegateObject(5,5) );
}
}
9. using System;
public delegate int Something(int a, int b);
class MyMath
{
public static int Add(int a, int b)
{
return a + b;
}
}
class MyMain
{
public static void Main() {
Something delegateObject = new Something(MyMath.Add);
// Calls Invoke!
Console.WriteLine( delegateObject(5,5) );
}
}
10. class MyMain
{
public static void Main() {
Something delegateObject = new Something(MyMath.Add);
PrintInformation(delegateObject);
}
// All delegates inherite Delegate class
public static void PrintInformation(Delegate delObj)
{
// Remember that delegate may hold number of methods!
foreach(Delegate d in delObj.GetInvocationList())
{
// Result: Int32 Add(Int32, Int32)
Console.WriteLine(d.Method);
}
}
}
12. class Teacher
{
// A new inner class is created here! The class inherits
// System.MulticastDelegate
// This can point to whatever class that is void and one string
// argument. This could be also outer-class.
public delegate void TeacherHandler(string msg);
// Declare an attribute type of the new class.
private TeacherHandler listOfHandlers;
// Helper method for assigning the attribute
public void RegisterWithListener(TeacherHandler methodToCall)
{
listOfHandlers = methodToCall;
}
public bool teacherIsBoring { get; set; }
public void teach()
{
// If teacher is not boring
if(!teacherIsBoring)
{
// And there are someone listening
if(listOfHandlers != null)
{
// Send message to the listener.
listOfHandlers("C# is cool!");
}
}
}
}
13. using System;
class MyMain
{
public static void Main()
{
Teacher jussi = new Teacher();
// instantiate inner class object
jussi.RegisterWithListener(new Teacher.TeacherHandler(OnTeachEvent));
jussi.teacherIsBoring = false;
jussi.teach();
}
// Since teacher is not boring and we are listening,
// this method is called
public static void OnTeachEvent(string m)
{
Console.WriteLine("Important message from teacher!");
Console.WriteLine(m);
}
}
15. // Helper method for assigning the attribute
public void RegisterWithListener(TeacherHandler methodToCall)
{
if(listOfHandlers == null)
{
listOfHandlers = methodToCall;
}
else
{
Delegate.Combine(listOfHandlers, methodToCall);
}
}
…
Teacher jussi = new Teacher();
// instantiate inner class object
jussi.RegisterWithListener(new Teacher.TeacherHandler(OnTeachEvent1));
jussi.RegisterWithListener(new Teacher.TeacherHandler(OnTeachEvent2));
jussi.teacherIsBoring = false;
jussi.teach();
16. // Helper method for assigning the attribute
public void RegisterWithListener(TeacherHandler methodToCall)
{
// And even more easier!
listOfHandlers += methodToCall;
}
…
Teacher jussi = new Teacher();
// instantiate inner class object
jussi.RegisterWithListener(new Teacher.TeacherHandler(OnTeachEvent1));
jussi.RegisterWithListener(new Teacher.TeacherHandler(OnTeachEvent2));
jussi.teacherIsBoring = false;
jussi.teach();
20. Method
Group
Conversion
• In
the
previous
example,
we
created
object
– Teacher.TeacherHandler
• You
don't
have
to
do
this!
• Method
group
conversion!
– Direct
method
name
is
converted
to
a
delegate
object
21. Method
Group
Conversion
public static void Main()
{
Teacher jussi = new Teacher();
jussi.RegisterWithListener(OnTeachEvent1);
jussi.RegisterWithListener(OnTeachEvent2);
jussi.teacherIsBoring = false;
jussi.teach();
jussi.UnRegisterWithListener(OnTeachEvent2);
jussi.teach();
}
23. Simplify
Registering
• The
previous
example
had
methods
like
– public
void
RegisterWithListener(TeacherHandler
methodToCall)
– public
void
UnRegisterWithListener(TeacherHandler
methodToCall)
• To
simplify
this,
we
can
use
events!
24. class Teacher
{
private int workHoursPerDay = 0;
public delegate void TeacherHandler(string msg);
// No register or unregister methods!
// When using events, two hidden methods are generated:
// add_AboutToOverload
// remove_AboutToOverLoad
public event TeacherHandler AboutToOverload;
public event TeacherHandler MentallyDead;
public void teach()
{
workHoursPerDay++;
if(workHoursPerDay >= 4 && workHoursPerDay < 6)
{
if(AboutToOverload != null)
{
AboutToOverload("TOO MUCH WORK FOR ME! Workhours = " + workHoursPerDay);
}
}
else if(workHoursPerDay >= 6)
{
if(MentallyDead != null)
{
MentallyDead("CANNOT WORK ANYMORE, BITCH ABOUT THIS! Workhours = " + workHoursPerDay);
}
}
}
}
25. class MyMain
{
public static void Main()
{
Student pekka = new Student();
pekka.Name = "Pekka";
Supervisor jaska = new Supervisor();
jaska.Name = "Jaska";
Teacher jussi = new Teacher();
jussi.AboutToOverload += pekka.listen;
jussi.AboutToOverload += jaska.listen;
jussi.MentallyDead += jaska.listen;
jussi.teach();
jussi.teach();
jussi.teach();
jussi.teach();
jussi.teach();
jussi.teach();
jussi.teach();
jussi.teach();
}
}
26. class Student
{
public string Name {get; set;}
public void listen(string m)
{
Console.WriteLine(Name + " listening to teacher msg = " + m);
}
}
class Supervisor
{
public string Name {get; set;}
public void listen(string m)
{
Console.WriteLine(Name + " listening to teacher msg = " + m);
}
}
28. class Student
{
public string Name {get; set;}
// Listener here get information:
// 1) who is the sender?
// 2) more information about the event
public void listen(object sender, TeacherEventArgs events)
{
Console.WriteLine(Name + " listening to teacher msg = " + events.msg);
}
}
class Supervisor
{
public string Name {get; set;}
public void listen(object sender, TeacherEventArgs events)
{
Console.WriteLine(Name + " listening to teacher msg = " + events.msg);
}
}
29. // Implement own custom event!
public class TeacherEventArgs : EventArgs
{
public readonly string msg;
public TeacherEventArgs(string message)
{
msg = message;
}
}
// And use it
class Teacher
{
private int workHoursPerDay = 0;
public delegate void TeacherHandler(object sender, TeacherEventArgs e);
…
public void teach()
{
…
AboutToOverload(this,
new TeacherEventArgs("TOO MUCH WORK …"));
…
}
31. public class TeacherEventArgs : EventArgs
{
public readonly string msg;
public TeacherEventArgs(string message)
{
msg = message;
}
}
class Teacher
{
private int workHoursPerDay = 0;
/*
public delegate void TeacherHandler(object sender, TeacherEventArgs e);
public event TeacherHandler AboutToOverload;
public event TeacherHandler MentallyDead;
*/
// Now we can use the EventHandler class. Notice that there is no
// need for the delegate anymore!
public event EventHandler<TeacherEventArgs> AboutToOverload;
public event EventHandler<TeacherEventArgs> MentallyDead;
32. class MyMain
{
public static void Main()
{
Student pekka = new Student();
pekka.Name = "Pekka";
Supervisor jaska = new Supervisor();
jaska.Name = "Jaska";
Teacher jussi = new Teacher();
// Now we can use the EventHandler class!
jussi.AboutToOverload += new EventHandler<TeacherEventArgs>(pekka.listen);
jussi.AboutToOverload += jaska.listen;
jussi.MentallyDead += jaska.listen;
35. Lambda
Expressions
• Lambda
expression
is
an
anonymous
funcon
that
you
can
use
to
create
delegates
• Can
be
used
to
write
local
funcons
that
can
be
passed
as
arguments
• Helpful
for
wring
LINQ
query
expressions
(we
will
see
this
later,
maybe
J)
jussi.AboutToOverload +=
(object sender, TeacherEventArgs events) =>
Console.WriteLine("hello");
37. System.Collecons
• All
Collecon
classes
can
be
found
from
System.Collecons
• Classes
like
– ArrayList
– Hashtable
• key/value
– Queue
• FIFO:
first-‐in,
first-‐out
– SortedList
• key/value,
sorted
by
the
keys
– Stack
• last-‐in,
first-‐out
38. Example
ArrayList list = new ArrayList();
list.Add("a");
list.Add("b");
list.add("c");
foreach(string s in list) { … }
39. Using
Generics
ArrayList<string> list = new
ArrayList<string>();
list.Add("a");
list.Add("b");
list.add("c");
list.add(2); // Fails
foreach(string s in list) { … }
40. Use
interfaces
• Use
this
– IList<string> list = new ArrayList<string>();
• Instead
of
this
– ArrayList<string> list = new Arraylist();
• You
can
change
the
collecon
class
later!