Evolution of C# delegates

1,102 views

Published on

Evolution of C# delegates - overview of delegates in C#, from basic delegates in C# 1.0 to lambda expressions on C# 4.0

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,102
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
69
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • - Delegate instanca će onemogućiti da garbage collector očisti njen target dok kod je ona živa. Ovo može stvoriti neželjeni memory leak jer će long-lived objekt (u našem slučaju instanca delegata) držati na životu short-lived objekt (u našem slučaju target)
  • Evolution of C# delegates

    1. 1. Evolution of C# delegates Marko Barić Senior software engineer @ Siemens CVC marko.baric@siemens.com
    2. 2. Agenda • Basic delegates • • • • • • • Delegate types, delegate instances Combining multiple delegates Method group conversions Covariance and contravariance Inline delegate actions Captured variables (closures) Lambda expressions
    3. 3. What is a delegate? • • • • Provide a level of indirection Sort of "sigle method interface" Delegates inhert from System.Delegate To create and use delegates: • • • • The delegate type needs to be declared The code to be executed must be contained in a method A delegate instance must be created The delegate instance must be invoked
    4. 4. Declaring delegate types delegate void StringProcessor(string input); keyword return type delegate type name arguments
    5. 5. Creating delegate instances class MyClass { public void SomeMethod(string input) public static void SomeMethodStatic(string input) } StringProcessor p1 = new StringProcessor(myClassInstance.SomeMethod); delegate instance variable delegate type action to invoke on MyClass instance StringProcessor p2 = new StringProcessor(MyClass.SomeMethod); static action to invoke on MyClass
    6. 6. Invoking delegates StringProcessor p1 = new StringProcessor(myClassInstance.SomeMethod); p1.Invoke("Some string"); // ...or shorter version p1("Some string"); p1("Some string"); p1.Invoke("Some string") SomeMethod("Some string") • Delegates can be treated like any other type • They have methods, multiple instance can be created...
    7. 7. Example delegate void StringProcessor(string input); class Person { private string name; public Person(string name) { this.name = name; } public void SayTheMessage(string message) { Console.WriteLine("{0} says: {1}", name, message); } public static void SayTheMessageStatic(string message) { Console.WriteLine(message); } } static void Main(string[] args) { Person john = new Person("John"); Person tom = new Person("Tom"); // Result: "John says: Hello!" "Tom says: Hello!" "Just saying something..." StringProcessor johnsVoice = new StringProcessor(john.SayTheMessage); StringProcessor tomsVoice = new StringProcessor(tom.SayTheMessage); StringProcessor someonesVoice = new StringProcessor(Person.SayTheMessageStatic); johnsVoice("Hello!"); tomsVoice.Invoke("Hello!"); someonesVoice("Just saying something..."); }
    8. 8. Combining the delegates • All delegates inherit methods from System.Delegate: • • Delegate.Combine() Delegate.Remove() • Every delegate has an invocation list - a list of actions to invoke • "+", "+=", "-", "-=" • When delegate is invoked, all actions in the invocation list are invoked in the order they were added
    9. 9. Example of combining delegates Person john = new Person("John"); Person tom = new Person("Tom"); Person mike = new Person("Mike"); StringProcessor johnsVoice = new StringProcessor(john.SayTheMessage); StringProcessor tomsVoice = new StringProcessor(tom.SayTheMessage); StringProcessor mikesVoice = new StringProcessor(mike.SayTheMessage); StringProcessor twoCombined = johnsVoice + tomsVoice; StringProcessor allCombined = twoCombined + mikesVoice; allCombined += new StringProcessor(john.SayTheMessage); allCombined("What's up!"); // Result: "John says: What's up!" "Tom says: What's up!" "Mike says: What's up!" "John says: What's up!"
    10. 10. Method group converions //Delegate type delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e); //Target action void LogKeyEvent(object sender, KeyPressEventArgs e) { /* do something */ } void LogKeyEvent(int x) { /* do something */ } button.KeyPress += new KeyPressEventHandler(LogKeyEvent); button.KeyPress += LogKeyEvent; Method group is converted to compatible delegate type
    11. 11. Contravariance of delegates Click -----> void EventHandler(object sender, EventArgs e) KeyPress -----> void KeyPressEventHandler(object sender, KeyPressEventArgs e) MouseClick ---> void MouseClickEventHandler(object sender, MouseEventArgs e) Button button = new Button(); button.Text = "Click me"; button.Click += LogPlainEvent; button.KeyPress += LogPlainEvent; button.MouseClick += LogPlainEvent; Same action for 3 different delegates! Form form = new Form(); form.Controls.Add(button); Application.Run(form); static void LogEvent(object sender, EventArgs e) { Console.WriteLine("An event occurred"); }
    12. 12. Covariance of delegates delegate Stream MyDelegate(); Stream static MemoryStream GenerateSampleData() { byte[] buffer = new byte[16]; return new MemoryStream(buffer); } MyDelegate d = GenerateSampleData(); Stream stream = d(); MemoryStream stream = d(); MemoryStream
    13. 13. Built-in delegate types in .NET delegate void Action<T>(T arg); delegate void Action<T1, T2>(T1 arg1, T2 arg2); ... delegate TResult Func<T, TResult>(T arg); delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); ... delegate bool Predicate<T>(T arg); ...
    14. 14. Inline delegate actions • You don't need action method to exist you can create it inline Action<int> printRoot = delegate(int number) { Console.WriteLine(Math.Sqrt(number)); }; printRoot(9); Invoke it like other delegates Func<string, int> getLength = delegate(string input) { return input.Length; }; int length = getLength("Some string");
    15. 15. Ingnoring inline delegate arguments • When you won't use delegate arguments you can loose them in definition button.Click += delegate(object sender, EventArgs e) { ... }; Button button = new Button(); button.Text = "Click me"; button.Click += delegate { Console.WriteLine("Click"); }; button.KeyPress += delegate { Console.WriteLine("KeyPress"); }; button.MouseClick += delegate { Console.WriteLine("MouseClick"); };
    16. 16. Ingnoring inline delegate arguments • Beware of the compiler limitations: // Thread class has several different constructors public Thread(ThreadStart start) public Thread(ParameterizedThreadStart start) // There are 2 types of delegates involved public delegate void ThreadStart() public delegate void ParameterizedThreadStart(object obj) new Thread(delegate() { Console.WriteLine("Something..."); } ); new Thread(delegate(object o) { Console.WriteLine("Something..."); } ); new Thread(delegate { Console.WriteLine("Something..."); } );
    17. 17. Captured variables (closures) • Captured variables are outer variables used (captured) in the scope of anonymous method void EnclosingMethod() { string outerVariable = "Default string"; Action<int> a = delegate() { string localVariable = outerVariable; }; a(); }
    18. 18. Captured variables delegate void MyDelegate(); string captured = "before x is created"; MyDelegate x = delegate { Console.WriteLine(captured); captured = "changed by x"; }; captured = "before x is invoked"; x(); Console.WriteLine(captured); captured = "before second invocation"; x(); // Result: "before x is invoked" "changed by x" "before second invocation" The captured variable is the same one that the outer code uses!!!
    19. 19. Lifetime of captured variables • A captured variable lives for at least as long as any delegate instance referring to it MethodInvoker CreateDelegateInstance() public { int counter = 5; MethodInvoker increment = delegate { Console.WriteLine(counter); counter++; }; increment(); return counter; } ... MethodInvoker x = CreateDelegateInstance(); x(); x();
    20. 20. Things can get tricky very fast MethodInvoker[] invokers = new MethodInvoker[2]; int outsideVariable = 0; for (int i=0; i<2; i++) { int insideVariable = 0; invokers[i] = delegate { Console.WriteLine ("({0},{1})", outsideVariable, insideVariable); outsideVariable++; insideVariable++; }; } MethodInvoker first = invokers[0]; // Result: MethodInvoker second = invokers[1]; (0,0) first(); first(); first(); second(); second(); (1,1) (2,2) (3,0) (4,1)
    21. 21. Lambda expressions • They are evolution of anonymous methods • More readable and compact than other delegate forms • Many shortcuts and "syntatic sugar" tricks allow most compat form of code • Brings new operator "=>" (spelled as "goes to")
    22. 22. Simple lambda expression delegate TResult Func<T, TResult>(T input); Func<string, int> returnLength; returnLength = delegate (string text) { return text.Length; }; (list of input arguments) => { statements } returnLength = (string text) => { return text.Length; }; input arguments statements
    23. 23. Shortening the lambdas returnLength = (string text) => { return text.Length; } If the statement is single expression, you can loose the braces, return statement and semicolon returnLength = (string text) => text.Length Compiler can guess type of input arguments, so you can loose it returnLength = (text) => text.Length If there is single input argument, you can loose the parentheses returnLength = text => text.Length
    24. 24. Let's recap Func<string, int> returnLength = new Func<string, int>(GetLength); returnLength(text); Func<string, int> returnLength = GetLength; returnLength(text); returnLength = delegate (string text) { return text.Length; }; returnLength = (string text) => { return text.Length; }; returnLength = text => text.Length;
    25. 25. Real-life lamba example - Where public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) { if (source == null || predicate == null) { throw new ArgumentNullExcpetion(); } foreach (T item in source) { if (predicate(item)) { yield return item; } } } // Usage: var items = new List<string> { "John", "Tom", "Mike" }; var filteredItems = items.Where(i => i.StartsWith("J"));
    26. 26. Real-life lambdas in action
    27. 27. Q & A?
    28. 28. Thank you!

    ×