Presentation is loading. Please wait.

Presentation is loading. Please wait.

How to work with indexers, delegates, events, and operators

Similar presentations


Presentation on theme: "How to work with indexers, delegates, events, and operators"— Presentation transcript:

1 How to work with indexers, delegates, events, and operators
Based on Murach (ch 13) and Deitel 2012

2 Objectives Applied Develop and use classes that have indexers
delegates events overloaded operators Knowledge Describe the use of an indexer. Explain why you should validate parameters and throw exceptions in your classes. Describe the use of delegates and events without and with anonymous methods and lambda expressions. Describe the use of operator overloading.

3 The code for a simple ProductList class (just an idea, based on Product class ch.12)
public class ProductList { private List<Product> products; public ProductList()//no parameters products = new List<Product>(); } public int Count => products.Count; public void Add(Product product) products.Add(product); public void Add(string code, string description, decimal price) Product p = new Product(code, description, price); products.Add(p); PROPERTY: Count of List - Gets the number of elements contained in the System.Collections.Generic.List. Returns: The number of elements contained in the System.Collections.Generic.List. (expression-bodied property) overloaded

4 Calls methods from another class ProductDB
The code for a simple ProductList class (just an idea, based on Product class ch.12 cont) public Product GetProductByIndex(int i) => products[i]; public void Remove(Product product) { products.Remove(product); } public void Fill() => products = ProductDB.GetProducts(); public void Save() => ProductDB.SaveProducts(products); Standard style, not expression-bodied Calls methods from another class ProductDB

5 Simple ProductList class (specification)

6 ProductList class cont.

7 Enhanced ProductList class (specification)

8 Indexers Indexers allow instances of a class or struct to be indexed like arrays. The indexed value can be set or retrieved without explicitly specifying a type or instance member. Indexers resemble properties except that their accessors take parameters.

9 1. An indexer that uses an integer as an index
Indexer is a special property private List<Product> products; //cannot access directly, private public Product this[int i] //no name { get return products[i]; //no validation yet } set products[i] = value;

10 2. A read-only indexer that uses a string as an index
public Product this[string code] { get foreach (Product p in products) if (p.Code == code) return p; } return null; //not found

11 3. A read-only indexer with an expression body (lambda)
(no “set” method) public Product this[int i] => products[i];

12 Using these 3 types indexers
First: Populating list ProductList products = new ProductList(); products.Add("CS15", "Murach's C# 2015", 56.50m); Accessing from list Product p1 = products[0]; //indexer using position Product p2 = products["CS15"]; //indexer code products[i] = new Product(code, description, price); public Product this[int i] { get{return products[i];} set{products[i] = value;} }

13 An indexer that checks the range and throws an argument exception
public Product this[int i] { get if (i < 0 || i >= products.Count) throw new ArgumentOutOfRangeException(i.ToString()); } return products[i]; ...

14 An indexer that validates data and throws an argument exception
public Product this[string code] { get if (code.Length > 4) throw new ArgumentException( "Maximum length of Code is 4 characters."); } foreach (Product p in products) //if code is valid search until found if (p.Code == code) return p; return null; //if NOT found

15 Three argument exceptions
Description ArgumentOutOfRangeException(message) Use when the value is outside the acceptable range of values. ArgumentNullException(message) Use when the value is null and a null value is not allowed. ArgumentException(message) Use when the value is invalid for any other reason.

16 Indexer Details An indexer is a special type of property that lets a user of the class access individual items within the class by specifying an index value. Indexers are used for classes that represent collections of objects. Before adding an indexer to a class, one should create an array or a collection as a private instance variable to hold the objects that will be accessed by the indexer. The declaration for an indexer includes the type of object it indexes, the this keyword, and a parameter that defines the index to be used, enclosed in brackets. The indexer’s get accessor should return the object specified by the index value that’s passed to it from the underlying collection. The indexer’s set accessor should set the object in the underlying collection that’s specified by the index that’s passed to it to the object passed via the value keyword. A read-only indexer that simply returns an expression can be coded as an expression—bodied indexer using the lambda operator. Although the index used by an indexer is typically an int, it doesn’t have to be.

17 Review Exceptions: Terminology*

18 Exception Keywords*

19 Running example* namespace UsingExceptions { class Program
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace UsingExceptions { class Program static void Main(string[] args) int x = 10; int y = 5; //0 int result; try result = x / y; Console.WriteLine("The result is: {0}", result); } catch Console.WriteLine("An error occurred! Better check the code!"); finally Console.WriteLine("Just proving that this code always runs."); Console.ReadLine(); }}}

20 Catching Specific Exceptions

21 Exceptions Hierarchy try { result = x / y;
Console.WriteLine("The result is: {0}", result); } catch (System.DivideByZeroException e) Console.WriteLine("Whoops! You tried to divide by zero!"); Console.WriteLine(e.Message); catch (System.ArithmeticException e)

22 More Specific Exceptions -> First. Try this *
{ result = x / y; Console.WriteLine("The result is: {0}", result); } catch (System.ArithmeticException e) Console.WriteLine("Whoops! You tried to divide by zero!"); Console.WriteLine(e.Message); catch (System.DivideByZeroException e) finally Console.WriteLine("Just proving that this code always runs."); Console.ReadLine();

23 Exceptions are Objects
System.Exception System.ApplicationException (non fatal exceptions)

24 Custom Exceptions

25 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CustomExceptions { public class MyOwnException : Exception public MyOwnException() : base("Laura Palmer is not welcomed here!") //Exception(string) //this.HelpLink = " us/library/system.exception.aspx"; }

26 { }//end of class }//end of namespace class Program
static void Main(string[] args) string theName; try theName = GetName(); Console.WriteLine("Hello {0}", theName); } catch (MyOwnException nje) Console.WriteLine(nje.Message); Console.WriteLine("For help, visit: {0}", nje.HelpLink); finally Console.WriteLine("Have a nice day!"); Console.ReadLine(); static string GetName() string s = Console.ReadLine(); if (s.Equals(“Laura")) throw new MyOwnException(); return s; }//end of class }//end of namespace

27 An if statement that validates data before setting a property value
Product p = null; if (txtCode.Text.Length <= 4) { p = products[txtCode.Text]; } However, you still need to validate in ProductLists because you cannot count on others, especially if your class is reusable (with public methods).

28 ArgumentOutOfRangeException
public Product thie[int i] { get if (i < 0 || i >= products.Count) throw new ArgumentOutOfRangeException(i.ToString()); } return products[i]:

29 Validates and throw argument exception
public Product this[string cede] { get if (cede.Length > 4) throw new ArgumentExceptien("Maximum length of Code is 4 char."); } foreach (Product p in products) if (p.Code == code) return p; return null;

30 Delegates Overall it is similar (but smarter) to the “old” C-function pointer, where functions can be assigned like a variable and called in the run time based on dynamic conditions. Type-safe function Delegate is defined with a specific signature (return type, parameter type and order etc.) To invoke a delegate object, one or more methods are required with the EXACT same signature. A delegate object is first created similar like a class object created. The delegate object will hold a reference of a function. The function will then can be called via the delegate object. Commonly used for event handlers

31 Simple Delegate Explanation cont.
1. Defining the delegate public delegate int Calculate (int value1, int value2); 2. Declare a variable that will hold a function of type Calculate private Calculate calculate; public static void Main() { // Assign the real function Add() to the variable Calculate calculate= Add; //can be Sub! // Call whatever function has been stored in the variable add Function int res = calculate( 1, 2 ); } // These functions matches EXACTLY the signature defined in the Math Function type private int Add( int n1, int n2 ) return n1 + n2; private int Sub( int n1, int n2 ) return n1 - n2;

32 Ex.: Delegate. Very Basic
namespace DelegateDemo { public delegate void HelloMethodDelegate(String msg); class Program static void Main(string[] args) //create instance of delegate, like ceate an object //instead of Hello("Hello World!"); HelloMethodDelegate helloDelegate = new HelloMethodDelegate(HelloMethod); helloDelegate("Hello World!"); Console.Read(); } //matching signature of delegate //try chang void to string -> error, because type safe public static void HelloMethod(String str) Console.WriteLine(str); >Hello World!

33 The syntax for declaring a delegate
public delegate returnType DelegateName([parameterList]); Code that declares a delegate in the ProductList class public delegate void ChangeHandler(ProductList products);

34 Code in a form that uses the delegate (idea)
public delegate void ChangeHandler(ProductList products); public partial class frmProducts : Form { // create the delegate object and identify the method it uses ProductList.ChangeHandler myDelegate = new ProductList.ChangeHandler(PrintToConsole); // a method with the same signature as the delegate private static void PrintToConsole(ProductList products) Console.WriteLine("The products list has changed!"); for (int i = 0; i < products.Count; i++) Product p = products[i]; Console.WriteLine(p.GetDisplayText("\t")); }

35 Code in a form that uses the delegate (idea) cont.
private void frmProducts_Load(object sender, EventArgs e) { // create the argument that's required by the delegate ProductList products = new ProductList(); // add products to the product list products.Add("BJWN", "Murach's Beginning Java with NetBeans", 57.50m); products.Add("CS15", "Murach's C# 2015", 56.50m); // call the delegate and pass the required argument myDelegate(products); }

36 Delegate Details (one more time)
A delegate is a type that can refer to methods with a specific return type and parameter list (the signature of the delegate). The return type and parameters are defined when the delegate is declared. To use a delegate, start by creating a delegate object and identifying the method it will use. This statement is typically coded at the class level so all the members of the class can use it. Then, you call the delegate and pass any arguments required by the method. A common use of delegates is to wire an event handler to an event so the event handler is called when the event is raised.

37 Event Details An event is a signal that an action has occurred on an object that was created from the class. To create an event that can be used by other classes, the event must be declared with public access at the class level. The event can be called from any properties or methods that need to raise the event. An event declaration specifies a delegate that will handle the event along with an event name. To raise the event, you refer to it by its name, and you code the arguments required by the delegate.- To handle an event from another class, you create an instance of the class that raises the event and assign it to a class variable. Then, you declare an event handler with a signature that matches the delegate’s signature. Finally, you wire the event handler to the event in the class constructor or, if the class is a form, in the Load event handler.

38 The syntax for declaring an event
An event is a signal that a particular action has occurred on an object that’s created from the class. Classes using that object can response by wiring event handler to it. [syntax] public event Delegate EventName; Code that declares and raises an event in the ProductList class public class ProductList { public delegate void ChangeHandler(ProductList products); public event ChangeHandler Changed; // declare the event public void Add(Product product) products.Add(product); Changed(this); // raise the event } ...

39 Nice youtube videos https://www.youtube.com/watch?v=G5R4C8BLEOc
Search for more…

40 Delegates and events 1. Define a delegate
2. Define an event based on that delegate 3. Raise the event May seem complex It is very flexible

41 Code in a form that wires the event handler and handles the event (idea)
ProductList products = new ProductList(); private void frmProducts_Load(object sender, System.EventArgs e) { // wire the event to the method that handles the event products.Changed += new ProductList.ChangeHandler(PrintToConsole); ... } // the method that handles the event private void PrintToConsole(ProductList products) Console.WriteLine("The products list has changed!"); for (int i = 0; i < products.Count; i++) Product p = products[i]; Console.WriteLine(p.GetDisplayText("\t"));

42 Another way: How to create a delegate using an anonymous method (no name method)
The same as printToConsole Ex.: ProductList.ChangeHandler myDelegate = delegate (ProductList products) { Console.WriteLine("The products list has changed!"); for (int i = 0; i < products.Count; i++) { ... } }; myDelegate(products); Ex.: using a lambda expression ProductList.ChangeHandler myDelegate = products =>

43 How wire an event using an anonymous method
products.Changed += delegate (ProductList products) { Console.WriteLine("The products list has changed!"); for (int i = 0; i < products.Count; i++) { ... } }; How wire an event using a lambda expression products.Changed += products =>

44 Anonymous Method An anonymous method is a method without a name. You can use an anonymous method when you create a delegate instead of specifying a named method. If the method is only called from one place, this can help simplify your code. A lambda expression. is similar to an anonymous method, but it uses the lambda operator instead of the delegate keyword. You can also wire an anonymous method or lambda expression to an event. When you do that, you should place the code in the class constructor, or if the class is a form, the Load event handler.

45 Overloading operators
C# defines meaning for built-in types (ex. +, ==) product1 == product2 (same Code, Description, Price) The syntax for overloading unary operators public static returnType operator unary-operator(type operand) Unary operators + - ! true false Ex: +x, -x, !x The syntax for overloading binary operators public static returnType operator binary-operator(type-1 operand-1, type-2 operand-2) Binary operators + - * / % & | == != > < >= <=

46 The Equals method of the Object class
Description Equals(object) Returns a Boolean value that indicates whether the current object refers to the same instance as the specified object. Equals(object1, object2) A static version of the Equals method that compares two objects to determine if they refer to the same instance. The GetHashCode method of the Object class Method Description GetHashCode() Returns an integer value that’s used to identify objects in a hash table. If you override the Equals method, you must also override the GetHashCode method.

47 Part of a ProductList class that overloads the + operator
public class ProductList { private List<Product> products; public void Add(Product p) products.Add(p); } public static ProductList operator + (ProductList pl, Product p) pl.Add(p); return pl; .

48 Code that uses the + operator of the ProductList class
ProductList products = new ProductList(); Product p = new Product("CS15", "Murach's C# 2015", 56.50m); products = products + p; Another way to use the + operator products += p;

49 Code that uses an expression-bodied operator
public ProductList Add(Product p) { products.Add(p); return this; } public static ProductList operator + ( ProductList pl, Product p) => pl.Add(p);

50 Code that overloads the == operator for a Product class (cont.)
To handle null public static bool == (Product p1, Product p2) { if (Object.Equals(p1 == null) //both null if (Object.Equals(p2 == null) return true; else return false; //p1 is null, p2 is not return p1.Equals(p2); } public static bool != (Product p1, Product p2) return !(p1 == p2); If == is overloaded -> need to overload != If > is overloaded -> need to overload <

51 Code that overloads the == operator for a Product class (cont.)
public override bool Equals(Object obj) { if (obj == null) //obviously return false; Product p = (Product)obj; if (this.Code == p.Code && this.Description == p.Description && this.Price == p.Price) return true; else } public override int GetHashCode() string hashString = this.Code + this.Description + this.Price; return hashString.GetHashCode();

52 Code that uses the == operator of the Product class
Product p1 = new Product("CS15", "Murach's C# 2015", 56.50m); Product p2 = new Product("CS15", "Murach's C# 2015", 56.50m); if (p1 == p2) // This evaluates to true. Without the // overloaded == operator, it would // evaluate to false (different objects).

53 The code for the Enhanced ProductMaintanace Behavior the same as in ch 12
Enhanced ProductList class Unchanged Products class Unchanged frmNewProduct class Changed frmProductMain class

54 The code for the Enhanced ProductMaintanace Behavior the same as in ch 12 Enhanced ProductList class
public class ProductList { private List<Product> products; public delegate void ChangeHandler(ProductList products); public event ChangeHandler Changed; public ProductList() products = new List<Product>(); } public int Count => products.Count; Event raises when products list are changed

55 The code for the ProductList class (cont.)
public Product this[int i] { get if (i < 0) throw new ArgumentOutOfRangeException("i"); } else if (i >= products.Count) return products[i]; set products[i] = value; Changed(this);

56 The code for the ProductList class (cont.)
public Product this[string code] { get foreach (Product p in products) if (p.Code == code) return p; } return null; public void Fill() => products = ProductDB.GetProducts(); public void Save() => ProductDB.SaveProducts(products);

57 The code for the ProductList class (cont.)
public void Add(Product product) { products.Add(product); Changed(this); } public void Add(string code, string description, decimal price) Product p = new Product(code, description, price); products.Add(p); public void Remove(Product product) products.Remove(product);

58 The code for the ProductList class (cont.)
public static ProductList operator +(ProductList pl, Product p) { pl.Add(p); return pl; } public static ProductList operator - (ProductList pl, Product p) pl.Remove(p);

59 The code for the Product Maintenance form
Instead of List<> it is ProductList Can utilize ProductList indexers Fill Method Save Method + Overloaded - Overloaded Changed event of products object In ProductList Changed event is raised any time a product is added or removed or changed in product list. Then the HandleChange method calls Save methods of products object and it call FillProductListBox to refresh the box.

60 The code for the Product Maintenance form
private ProductList products = new ProductList(); private void frmProductMain_Load(object sender, EventArgs e) { products.Changed += new ProductList.ChangeHandler(HandleChange); products.Fill(); FillProductListBox(); } private void FillProductListBox() Product p; lstProducts.Items.Clear(); for (int i = 0; i < products.Count; i++) p = products[i]; lstProducts.Items.Add(p.GetDisplayText("\t"));

61 The code for the Product Maintenance form cont.
private void btnAdd_Click(object sender, EventArgs e) { frmNewProduct newForm = new frmNewProduct(); Product product = newForm.GetNewProduct(); if (product != null) { products += product; } private void btnDelete_Click(object sender, EventArgs e) int i = lstProducts.SelectedIndex; if (i != -1) Product product = products[i]; string message = "Are you sure you want to delete " + product.Description + "?"; DialogResult button = MessageBox.Show(message, "Confirm Delete", MessageBoxButtons.YesNo); if (button == DialogResult.Yes) products -= product;

62 The code for the Product Maintenance form cont.
private void btnExit_Click(object sender, EventArgs e) { this.Close(); } private void HandleChange(ProductList products) products.Save(); FillProductListBox();

63 Project 3-3 Direct a simple robot
Create a form that lets the user move a simple robot a given direction and distance, and create a class that performs the robot movements.


Download ppt "How to work with indexers, delegates, events, and operators"

Similar presentations


Ads by Google