Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Wednesday, 15 October 2014

Language Integrated Query
LINQ provides a general purpose query facility

MS… IEnumerable<T>

static void Main() { // Can hide anything behind IEnumerable eg a database // doesn't define interesting methods.. so MS added extension methods IEnumerable<string> cities = new[] { "Ghent", "London", "Las Vegas", "Hyderbad" }; foreach (var city in cities) { Console.WriteLine(city); } }


Utility class - old way of doing it:

class Program { static void Main() { var date = new DateTime(2002, 8,9); int daysTillEndOfMonth = DateUtilities.DaysToEndOfMonth(date); Console.WriteLine(daysTillEndOfMonth); } } public static class DateUtilities { public static int DaysToEndOfMonth(DateTime date) { return DateTime.DaysInMonth(date.Year, date.Month) - date.Day; } }

By adding this we have an extension method.

class Program { static void Main() { var date = new DateTime(2002, 8,9); // Using an extension method int daysTillEndOfMonth = date.DaysToEndOfMonth(); Console.WriteLine(daysTillEndOfMonth); } } public static class DateUtilities { public static int DaysToEndOfMonth(this DateTime date) { return DateTime.DaysInMonth(date.Year, date.Month) - date.Day; } }

Compiler trick.  Makes the syntax nice. Extension method needs to be in the same namespace.

using System; using System.Collections.Generic; using Extensions; namespace Grades { class Program { static void Main() { // Can hide anything behind IEnumerable eg a database // doesn't define interesting methods.. so MS added extension methods IEnumerable<string> cities = new[] { "Ghent", "London", "Las Vegas", "Hyderbad" }; // Take this datasource, and give me all citites that start with L IEnumerable<string> query = cities.StringThatStartsWith("L"); foreach (var city in query) { Console.WriteLine(city); } } } } namespace Extensions { public static class FilterExtensions { // Extension method for IEnumerable<string> // Data source is IEnumerable<string> public static IEnumerable<string> StringThatStartsWith(this IEnumerable<string> input, string start) { foreach (var s in input) { if (s.StartsWith(start)) { // builds an IEnumerable yield return s; } } } } }

Implementing a simple extension method on IEnumerable<string>
This is the way that LINQ operators are defined.
static void Main() { // Can hide anything behind IEnumerable eg a database // doesn't define interesting methods.. so MS added extension methods IEnumerable<string> cities = new[] { "Ghent", "London", "Las Vegas", "Hyderbad" }; // A very generic operator..need to look at lambda expressions. cities.Where() // Take this datasource, and give me all citites that start with L IEnumerable<string> query = cities.StringThatStartsWith("L"); foreach (var city in query) { Console.WriteLine(city); } }

Lambda Expressions

Making more flexible with a delegate.. So can have an IEnumerable<T>

class Program { static void Main() { IEnumerable<string> cities = new[] { "Ghent", "London", "Las Vegas", "Hyderbad" }; // More flexible, as have a Filter method that can take delegates // that point to other things IEnumerable<string> query = cities.Filter(StringTheStartWithL); foreach (var city in query) { Console.WriteLine(city); } } static bool StringTheStartWithL(string s) { return s.StartsWith("L"); } } public static class FilterExtensions { public static IEnumerable<T> Filter<T> (this IEnumerable<T> input, FilterDelegate<T> predicate) { // foreach item in the input, invoke the predicate (method) // if predicate returns true, add to IEnumerable returning foreach (var item in input) { if (predicate(item)) { // builds an IEnumerable yield return item; } } } } public delegate bool FilterDelegate<T>(T item);


A more flexible approach than writing an extension method for each case
// C#2 Anonymous delegate IEnumerable<string> query = cities.Filter(delegate(string item) { return item.StartsWith("L"); });

This does exactly the same – don’t need a named method.  Can inline it.  A delegate calling an anonymous method.

Goes to operator

// Lambda expression.. LHS is signature of the method (takes a string - type inference) // Body returns a bool of item.StartsWith("L") IEnumerable<string> query = cities.Filter(item => item.StartsWith("L")); foreach (var city in query) { Console.WriteLine(city); }

Lambdas are the way to write delegates in C#3 and above

Func

Passing around small snippets of information to express how to perform an operation – very interesting!

Func is a generic type which encapsulates delegates (callable code)

// Delegate that takes an integer as a parameter, and returns a bool //Func<int, bool> Func<int, int> square = x => x * x; // Parameters requied for 0 or 2+ parameters Func<int, int, int> add = (x, y) => x + y; Console.WriteLine(square(3)); Console.WriteLine(add(3,4)); // Action is just like Func with no return value Action<int> write = x => Console.WriteLine(x); write(16);


Great thing about Func is we no longer need to define delegates
public static class FilterExtensions { // By using Func<T,bool> we don't need to define a delegate public static IEnumerable<T> Filter<T> (this IEnumerable<T> input, Func<T,bool> predicate) { // foreach item in the input, invoke the predicate (method) // if predicate returns true, add to IEnumerable returning foreach (var item in input) { if (predicate(item)) { // builds an IEnumerable yield return item; } } } public static IEnumerable<T> Filterx<T> (this IEnumerable<T> input, FilterDelegate<T> predicate) { // foreach item in the input, invoke the predicate (method) // if predicate returns true, add to IEnumerable returning foreach (var item in input) { if (predicate(item)) { // builds an IEnumerable yield return item; } } } } public delegate bool FilterDelegate<T>(T item);

Using the inbuilt extension method which is just like above using a Func<T>
IEnumerable<string> query = cities.Where(city => city.StartsWith("L")) .OrderByDescending(city => city.Length);

Start of Funcs and Expressions.

| | # 
# Monday, 13 October 2014
( c# | Delegate | Events )
  • Allows a class to send notifications to other classes or objects
    • Publisher raises the event
    • One or more subscribers process the event

eg Button –> click –> subscriber1, subscriber2

Events are based on delegates

Delegates

  • I need a variable that references a method
  • A delegate is a type that references methods (just like a class or struct)
    • public delegate void Writer(string message);

Delegates can be very useful.

// The type public delegate void NameChangedDelegate(string oldValue, string newValue); static void Main() { // NameChanged variable references a method OnNameChanged NameChangedDelegate NameChanged = new NameChangedDelegate(OnNameChanged); NameChanged("old", "new"); } // This method will execute when a private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); }

and..

public delegate float RateDelegate(float a); private static float OnRate(float a) { throw new NotImplementedException(); } static void Main() { //RateDelegate rate = new RateDelegate(OnRate); // rate is a delegate variable RateDelegate rate; rate = (float a) => a*2; float x = 2f; float y = rate(x); float yy = rate(x);

Interesting code showing a delegate type being assigned to a method, and anonymous method.

 

eg want to know what

multiple subscribers to listen.. this is what events are for.

// Backing field (private) private string _name; public string Name { get { return _name; } set { if (_name != value) { var oldValue = _name; _name = value; // Announce to world that something has changed if (NameChanged != null) { // It has no idea what will be called, only that the signature will be string oldValue, string newValue NameChanged(oldValue, value); } } } } // Field of type NameChangedDelegate public NameChangedDelegate NameChanged;

Type:
public delegate void NameChangedDelegate(string oldValue, string newValue);

Listeners:
{ //... // Hooking up the delegate to point to another method // Setting the public Field (of type NameChangedDelegate) to a new delegate and passing the method // however anyone else can overwrite this //book.NameChanged = new NameChangedDelegate(OnNameChanged); // multicast delegate book.NameChanged += OnNameChanged; book.NameChanged += OnNameChanged; book.NameChanged += OnNameChanged2; // ahh would wipe out the previous ones book.NameChanged = new NameChangedDelegate(OnNameChanged2); book.Name = "Allen's Book"; WriteNames(book.Name); Console.WriteLine(stats.AverageGrade); Console.WriteLine(stats.LowestGrade); Console.WriteLine(stats.HighestGrade); } private static void OnNameChanged2(string oldvalue, string newvalue) { Console.WriteLine("***"); } // This method will execute when a private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); }

Notice the error above – wipes out the previous method delegate calls.

Next to use an event – prevent wiping out subscribers.

Events

Events are just delegates. 0:11 of 8:35

class Program { // The type public delegate void NameChangedDelegate(string oldValue, string newValue); static void Main() { // NameChanged variable references a method OnNameChanged NameChangedDelegate nameChanged = new NameChangedDelegate(OnNameChanged); nameChanged("old", "new"); } // This method will execute when a private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); } }

Here is the working code with a delegate

class Program2 { // The type public delegate void NameChangedDelegate(string oldValue, string newValue); public static event NameChangedDelegate NameChanged; static void Main() { // NameChanged variable references a method OnNameChanged NameChanged += new NameChangedDelegate(OnNameChanged); NameChanged("old", "new"); } private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); } }

Same with an Event.

class Program3 { public delegate void NameChangedDelegate(object sender, NameChangedEventArgs e); public static event NameChangedDelegate NameChanged; static void Main() { // NameChanged variable references a method OnNameChanged NameChanged += new NameChangedDelegate(OnNameChanged); //Convention in events: never pass arbitrary params NameChanged(null, new NameChangedEventArgs {OldValue = "old", NewValue = "new"}); } private static void OnNameChanged(object sender, NameChangedEventArgs e) { Console.WriteLine("Name changed from {0} to {1}", e.OldValue, e.NewValue); } } public class NameChangedEventArgs : EventArgs { public string OldValue { get; set; } public string NewValue { get; set; } }

Event using EventArgs (convention).  Using a static method so had to pass null instead of this.

 

Syntactically the same

public event NameChangedDelegate NameChanged;
No longer legal to assign to an event (which wiped out previous method delegate calls above)

Thats what special about events – needs a += or –= assignment

public class NameChangedEventArgs : EventArgs { public string OldValue { get; set; } public string NewValue { get; set; } }

Derives from EventArgs
public delegate void NameChangedDelegate(object sender, NameChangedEventArgs args);
 
private static void OnNameChanged(object sender, NameChangedEventArgs args){ Console.WriteLine("Name changed from {0} to {1}", args.OldValue, args.NewValue); }
Convention in events: never pass arbitrary params.. sender (eg gradebook) itself, then object that encapsulates other stuff

Members

Members are used to craft an abstraction

  • Fields and properties for state
  • Methods for behaviour
  • Events for notification
| | #