34
Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Embed Size (px)

Citation preview

Page 1: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C# Extension Methods

CSE 459.24Prof. Roger Crawfis

Page 2: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Extension Methods

Can add methods to other classesLet me repeat that: Can add methods to

other classes any methods (although they look static) only from static classes

When you import a namespace that has extensions, these are added to classes once imported, called as usual instance methods

Local methods take precedence

Page 3: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Extension Methods

public static class Extensions   {

    public static int ToInt32(this string integerString)

{

      return Int32.Parse(integerString);

    }

    public static T[] Slice<T>(this T[] source, int startIndex, int count)

    {

        if (startIndex < 0 || count < 0 || (source.Length - startIndex) < count)

            throw new InvalidArgumentException();

        T[] result = new T[count];

        Array.Copy(source, startIndex, result, 0, count);

        return result;

    }

}

Page 4: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Extension Methods

Properties, events and operators can not have extension methods.

Equivalent to calling the static methodCan only access public methods, etc.

Allows for chaining method calls.More later when we talk about LINQ.

Page 5: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Extension Method Example

public static class MyExtensions {      

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count) {

          Queue<T> saveList = new Queue<T>();

          int saved = 0;

          foreach (T item in source)         {

              if (saved < count)             {

                  saveList.Enqueue(item);

                  ++saved;

                  continue;

              }

              saveList.Enqueue(item);

              yield return saveList.Dequeue();

          }

          yield break;

    }

}

http://blogs.msdn.com/ericwhite/archive/2008/11/14/the-skiplast-extension-method.aspx

Page 6: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Extension Method Example

class Program {

     static void Main(string[] args)    {

         int[] a = new[] { 1, 2, 3, 4, 5 };

         var b = a.SkipLast(2); 

        foreach (var item in b)

             Console.WriteLine(item);

         var c = new List<string>() { "one", "two", "three", "four", "five"  };

         var d = c.Skip(1).SkipLast(1);

         foreach (var e in d)

             Console.WriteLine(e);

     }

}

123twothreefour

Page 7: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C#Extension Methods

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Page 8: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C# Types - Misc

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Page 9: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Initializers

We already know how to initialize basic types:int index = 0;

string message = “Save the Cheerleader”;

And complex types using constructors:Person paul = new Person(“Paul”, “Newman”);

IList<string> words = new List<string>(35);

Can also use initializers to set properties and initialize collections.

Page 10: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Initializers

Can initialize fields or properties. new C(1, 2) {Name=“my class”}; Works if public field or a property with public set Point a = new Point { X = 0, Y = 1 }; Can be nested (eg. Rectangle with two Points)

Collection initializers List<int> digits = new List<int> { 0, 1}; Must implement System.Generic.ICollection<T>

Page 11: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Initializers Example

public class Student{

    public string firstName;

    public string lastName;

}

public class ScienceClass{

    public Student Student1, Student2, Student3;

}

static void Main(string[] args){

    var student1 = new Student { firstName = "Bruce", lastName = "Willis“ };

    var student2 = new Student { firstName = "George", lastName = "Clooney"};

    var student3 = new Student { firstName = "James", lastName = "Cameron“ };

    var sClass = new ScienceClass { Student1 = student1, Student2 = student2, Student3 = student3 };

}

Page 12: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Initializers Example

// Using a Constructor

Person p = new Person("John", "Doe", "602-123-1234");

// Using Properties and an initializer

Person p = new Person() { FirstName="John", LastName="Doe", Phone="602-123-1234", City="Phoenix"};

// Adding a composite type

Person p = new Person() {

FirstName = "John",

LastName = "Doe",

Address = new Address() {

Street = "1234 St.",

City = "Phoenix“

}

};

Page 13: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Implicitly Typed Variables

Type of the variable induced from expression Must include an initializer Can not be null.

var i = 5;

var s = "Hello";

var d = 1.0; // Did you really mean a double?

var orders = new Dictionary<int,Order>();

var a = new Point { X = 0, Y = 1 };

Page 14: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Implicitly Typed Variables

Implicitly typed arraysvar a = new[ ] { 1, 10, 100, 1000 }; Must have consistent types or have implicit

conversions

Page 15: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Anonymous Types

var x = new {p1 = 10, p2 = “name”};x is an anonymous typeAn anonymous type can not be referred to

by name in a program.Structural type equivalence

Two anonymous types can be compatibleWhy in the world would we want these?

Again, needed/useful for LINQ.

Page 16: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Anonymous Types Example

protected object AnonymousTypes()    {

        // *** Create Complex Types 'on the fly‘

        var Customer = new {

            Company = "West Wind",

            Name = "Rick",

            Entered = DateTime.Now,

            BillRate = 150M,

            Contacts = new {

                Phone = "808 121-1211",

                Fax = "808 231-1211",

                Email = [email protected]

            }

        };

         return Customer;

    }http://www.west-wind.com/weblog/posts/189329.aspx

Page 17: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C# Types - Misc

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Page 18: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C#Anonymous Methods

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Page 19: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Anonymous Method Example

Becomes quite cumbersome to create little methods for each specialization. These methods are only used in one context.

The use and declaration are disjoint. Would be nice to have the declaration in-line.

personList.RemoveAll( delegate(Person person) {

    return person.DateOfBirth.Year < 1980;

});

Page 20: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Anonymous Methods

Delegates are clumsy: programmer has to name the function and “closure-convert” by hand

C# 2.0 introduced anonymous methods No name Compiler does closure-conversion, creating a class and object that

captures the environment e.g.

        bool b = xs.Exists(delegate(int x) { return x > y; });

Local y is free in body of anonymous method

Page 21: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Anonymous Methods

Further simplification

Button button = new Button();Button.Click += delegate (object sender, EventArgs arg) { Console.WriteLine("clicked"); };

Can be simplified as follows

Button.Click += delegate { Console.WriteLine("clicked"); };

Formal parameters can be omitted if they are not used in the method body

delegate void EventHandler (object sender, EventArgs arg);

Page 22: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Outer Variables

If anonymous methods access variables of the enclosing method, these variables are evacuated into a dummy object (capturing)

The anonymous method and the enclosing method itself are then using a single evacuated variable

delegate int Adder();static Adder CreateAdder() {               

int x = 0;return delegate { x++; return x; };}public static void Main() {Adder add = CreateAdder();Console.WriteLine(add());Console.WriteLine(add());Console.WriteLine(add());add = CreateAdder();Console.WriteLine(add());Console.WriteLine(add());Console.WriteLine(add());}

123123

Output:

x++; return x;

0dummy object

delegate

add123

The dummy object lives as long as the delegate object

Page 23: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Anonymous Method Example

delegate void MyDelegate();

class Program {

    static MyDelegate Foo() {

        int x = 1;

        Console.WriteLine("Foo: x = {0}", x);

        MyDelegate d = delegate { x++; Console.WriteLine("delegate: x = {0}", x); };

        d();  d();

        Console.WriteLine("Foo: x = {0}", x);

        MyDelegate d2 = delegate { x += 10; Console.WriteLine("second delegate: x = {0}", x); };

        d2();  d();

        Console.WriteLine("Foo: x = {0}", x);

        return d2;

    }

--- Main: Foo()();Foo: x = 1delegate: x = 2delegate: x = 3Foo: x = 3second delegate: x = 13delegate: x = 14Foo: x = 14second delegate: x = 24--- Main: Foo()();Foo: x = 1delegate: x = 2delegate: x = 3Foo: x = 3second delegate: x = 13delegate: x = 14Foo: x = 14second delegate: x = 24

     static void Main(string[] args) {        Console.WriteLine("--- Main: Foo()();");        Foo()();        Console.WriteLine("--- Main: Foo()();");        Foo()();    }}

Page 24: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C#Anonymous Methods

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Page 25: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C#Lambda Expressions

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Page 26: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Lambda Expressions

Generalized function syntax x . x + 1 in C# 3.0, have x => x + 1

From anonymous delegate syntax:delegate(int x) { return x + 1;}

Can have implicitly typed variablesCan have more than one variableCan have expression or statement body

Page 27: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Lambda Expressions

Expression or statement body Implicitly or explicitly typed parameters Examples: x => x + 1 // Implicitly typed, expression body x => { return x + 1; } // Implicitly typed, statement body (int x) => x + 1 // Explicitly typed, expression body (int x) => { return x + 1; } // Explicitly typed, statement body (x, y) => x * y // Multiple parameters () => Console.WriteLine() // No parameters personList.RemoveAll(p => p.DateOfBirth.Year < 1980);

Page 28: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Lambda Expressions

Lambda expressions participate in inference process of type arguments of generic methods

In initial phase, nothing is inferred from arguments that are lambda expressions

Following the initial phase, additional inferences are made from lambda expressions using an iterative process

Page 29: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Lambda Expressions

Type inferencepublic static IEnumerable<S> Select<T,S>( this

IEnumerable<T> source, Func<T,S> selector)

{

foreach (T element in source)

yield return selector(element);

}

If call Select(customers, c => c.Name);T, S mapped to appropriate types

Page 30: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Lambda Expressions

Generic extension method example:

Calling extension method with lambda expression:List<Customer> customers = GetCustomerList();IEnumerable<string> names = customers.Select(c => c.Name);

Rewriting extension method call:IEnumerable<string> names = Sequence.Select<T, S>(customers, c => c.Name);

T type argument is inferred to Customer based on source argument typeSequence.Select<Customer, S>(customers, c => c.Name)

c lambda expression argument type is inferred to CustomerSequence.Select<Customer, S>(customers, (Customer c) => c.Name)

S type argument is inferred to string based on return value type of the lambda expression

Sequence.Select<Customer, string>(customers, (Customer c) => c.Name)

public static class Sequence {    public static IEnumerable<S> Select<T,S>(this IEnumerable<T> source, Func<T, S> selector) {        foreach (T element in source) yield return selector(element); } }

Page 31: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Lambda Expressions

A lambda expression is a value, that does not have a type but can be implicitly converted to a compatible delegate typedelegate R Func<A,R>(A arg);

Func<int,int> f1 = x => x + 1;

Func<int,double> f2 = x => x + 1;

Func<double,int> f3 = x => x + 1; // Error double -> int

Page 32: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Lambda Expressions

Given the codedelegate R Func<A,R>(A arg);

static Z F<X,Y,Z>(X x, Func<X,Y> f1, Func<Y,Z> f2)

{

return f2(f1(x));

}

What does the following produce?F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds)

Page 33: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Extension Methods, …

Try this at home! Let’s wrap this discussion up by combining extension methods, implicit types, anonymous types and lambda expressions to create a complex process chain:

var processes =

System.Diagnostics.Process.GetProcesses()

.Where(proc => proc.WorkingSet64 > 20 * 1024 * 1024)

.OrderByDescending(proc => proc.WorkingSet64)

.Select(proc =>

new { Identifier = proc.Id, Name = proc.ProcessName });

foreach (var process in processes)Console.WriteLine("Identifier = {0}, Name = {1}", process.Identifier, process.Name);

Page 34: Extension Methods Programming in C# Extension Methods CSE 459.24 Prof. Roger Crawfis

Programming in C# Lambda Expressions

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis