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

Programming in C# Extension Methods

Embed Size (px)

DESCRIPTION

Programming in C# Extension Methods. CSE 459.24 Prof . Roger Crawfis. Extension Methods. Can add methods to other classes Let me repeat that: Can add methods to other classes any methods (although they look static) only from static classes - PowerPoint PPT Presentation

Citation preview

Page 1: Programming in C# Extension Methods

Programming in C# Extension Methods

CSE 459.24Prof. Roger Crawfis

Page 2: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

Programming in C#Extension Methods

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

Prof. Roger Crawfis

Page 8: Programming in C# Extension Methods

Programming in C# Types - Misc

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

Prof. Roger Crawfis

Page 9: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

Implicitly Typed Variables

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

conversions

Page 15: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

Programming in C# Types - Misc

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

Prof. Roger Crawfis

Page 18: Programming in C# Extension Methods

Programming in C#Anonymous Methods

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

Prof. Roger Crawfis

Page 19: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

Programming in C#Anonymous Methods

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

Prof. Roger Crawfis

Page 25: Programming in C# Extension Methods

Programming in C#Lambda Expressions

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

Prof. Roger Crawfis

Page 26: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

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: Programming in C# Extension Methods

Programming in C# Lambda Expressions

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

Prof. Roger Crawfis