Equality Programming in C# Equality CSE / ECE 668 Prof. Roger Crawfis.

Slides:



Advertisements
Similar presentations
Generics Programming in C# Generics CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis.
Advertisements

Generics, Lists, Interfaces
CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics C# Language &.NET Platform 12 th -13 th Lecture Pavel Ježek.
Language Fundamentals in brief C# - Introduction.
Problem Solving 5 Using Java API for Searching and Sorting Applications ICS-201 Introduction to Computing II Semester 071.
Lecture 11 oct 6 Goals: hashing hash functions chaining closed hashing application of hashing.
Equality Programming in C# Equality CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis.
Searching. 2 Searching an array of integers If an array is not sorted, there is no better algorithm than linear search for finding an element in it static.
Searching and Sorting I 1 Searching and Sorting 1.
ICS201 Lecture 20 : Searching King Fahd University of Petroleum & Minerals College of Computer Science & Engineering Information & Computer Science Department.
1 Evan Korth New York University Inheritance and Polymorphism Professor Evan Korth New York University.
1 Java Object Model Part 2: the Object class. 2 Object class Superclass for all Java classes Any class without explicit extends clause is a direct subclass.
Searching. 2 Searching an array of integers If an array is not sorted, there is no better algorithm than linear search for finding an element in it static.
1 Evan Korth New York University Inheritance and Polymorphism Professor Evan Korth New York University.
Searching. Searching an array of integers If an array is not sorted, there is no better algorithm than linear search for finding an element in it static.
Chapter 10 Classes Continued
Comparing Objects in Java. The == operator When you define an object, for instance Person p = new Person("John", 23); we talk about p as if its value.
Searching Also: Logarithms. 2 Searching an array of integers If an array is not sorted, there is no better algorithm than linear search for finding an.
(c) University of Washingtonhashing-1 CSC 143 Java Hashing Set Implementation via Hashing.
11 Values and References Chapter Objectives You will be able to: Describe and compare value types and reference types. Write programs that use variables.
CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics C# Language &.NET Platform 7 th & 8 th Lecture Pavel Ježek.
BASE CLASSES AND INHERITANCE CHAPTER 4. Engineer Class.
CSE 332: C++ templates This Week C++ Templates –Another form of polymorphism (interface based) –Let you plug different types into reusable code Assigned.
Searching Also: Logarithms. 2 Searching an array of integers If an array is not sorted, there is no better algorithm than linear search for finding an.
FEN 2012 UCN Technology: Computer Science1 C# - Introduction Language Fundamentals in Brief.
Method Overriding Remember inheritance: when a child class inherits methods, variables, etc from a parent class. Example: public class Dictionary extends.
Object-oriented Programming in Java. What is OOP?  The goal is (subtype) polymorphism  Achieved by Classes (user-defined types) Classes (user-defined.
Puzzle 3 1  Write the class Enigma, which extends Object, so that the following program prints false: public class Conundrum { public static void main(String[]
Non-static classes Part 2 1. Methods  like constructors, all non-static methods have an implicit parameter named this  for methods, this refers to the.
APCS Java AB 2004 Review of CS1 and CS2 Review for AP test #1 Sources: 2003 Workshop notes from Chris Nevison (Colgate University) AP Study Guide to go.
Effective C#, Chapter 1: C# Language Elements Last Updated: Fall 2011.
Delegates Programming in C# Delegates CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis.
Session 08 Module 14: Generics and Iterator Module 15: Anonymous & partial class & Nullable type.
Modern Software Development Using C#.NET Chapter 5: More Advanced Class Construction.
Chapter 18 Java Collections Framework
Chapter 3 Inheritance and Polymorphism Goals: 1.Superclasses and subclasses 2.Inheritance Hierarchy 3.Polymorphism 4.Type Compatibility 5.Abstract Classes.
1 TCSS 143, Autumn 2004 Lecture Notes Creating Java Classes.
Chapter 10 Defining Classes. The Internal Structure of Classes and Objects Object – collection of data and operations, in which the data can be accessed.
HashCode() 1  if you override equals() you must override hashCode()  otherwise, the hashed containers won't work properly  recall that we did not override.
Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual.
ENEE150 – 0102 ANDREW GOFFIN Project 4 & Function Pointers.
1 COSC2007 Data Structures II Chapter 9 Class Relationships.
PROGRAMMING IN C#. Collection Classes (C# Programming Guide) The.NET Framework provides specialized classes for data storage and retrieval. These classes.
Dictionaries, Hash Tables, Collisions Resolution, Sets Svetlin Nakov Telerik Corporation
Method Overriding Remember inheritance: when a child class inherits methods, variables, etc from a parent class. Example: public class Dictionary extends.
Changing Comparison Programming in C# Changing Comparison CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis.
Sets and Maps Part of the Collections Framework. 2 The Set interface A Set is unordered and has no duplicates Operations are exactly those for Collection.
1 C# - Inheritance and Polymorphism. 2 1.Inheritance 2.Implementing Inheritance in C# 3.Constructor calls in Inheritance 4.Protected Access Modifier 5.The.
Recap Introduction to Inheritance Inheritance in C++ IS-A Relationship Polymorphism in Inheritance Classes in Inheritance Visibility Rules Constructor.
Effective C# Item 10 and 11. Understand the Pitfalls of GetHashCode Item 10.
Inheritance and Polymorphism
CSC142 NN 1 CSC 142 Overriding methods from the Object class: equals, toString.
Arrays and Indexers Programming in C# Arrays and Indexers CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis.
Collections Dwight Deugo Nesa Matic
CPS What's in Compsci 100? l Understanding tradeoffs: reasoning, analyzing, describing…  Algorithms  Data Structures  Programming  Design l.
Chapter  Array-like data structures  ArrayList  Queue  Stack  Hashtable  SortedList  Offer programming convenience for specific access.
Introduction C# program is collection of classes Classes are collection of methods and some statements That statements contains tokens C# includes five.
1 clone() Defined in Object Creates an identical copy –Copies pointers to fields (does not copy fields of fields) –Makes a shallow copy if the object’s.
Value Types. 2 Objectives Discuss concept of value types –efficiency –memory management –value semantics –boxing –unboxing –simple types Introduce struct.
Searching.
Object-oriented Programming in Java
16: Equals Equals Programming C# © 2003 DevelopMentor, Inc. 12/1/2003.
5.1 Being Objects and A Glimpse into Coding
Programming in C# Comparison (Sorting)
Searching.
CIS 199 Final Review.
Binding 10: Binding Programming C# © 2003 DevelopMentor, Inc.
Review for Midterm 3.
Presentation transcript:

Equality Programming in C# Equality CSE / ECE 668 Prof. Roger Crawfis

Equality What does it mean for to variables to be equal: Numeric types – easy Strings – some caveats Employee records - ?

Equality Two basic types of equality: Value equality Two variables are equal if they have the same value (mean the same thing). Referential equality Two variables are equal if they refer to the same instance (pointer or storage equality). Difference: Are two 2008 Lamborghini Gallardo’s equal? Theoretically, it depends on the context.

Default Equality As expected, all value types have value- based equality. double a = 1.2; double b = 1.2; bool areEqual = a == b; // true. Strings also have value equality. string name = “Crawfis”; string instructor = “Crawfis”; bool areEqual = a == b; // true.

Default Equality What is the default equality for classes? In C++ there is none. In C# there is. It is referential equality. class foo {…}; foo A = new foo(); foo B = new foo(); bool areEqual = A == B; // false. object C = A; // C refers to the same instance as A. bool areEqual = C == A; // true.

Default Equality Subtleties: int[] a = {0,1,2,3}; int[] b = {0,1,2,3}; int[] a = {0,1,2,3}; int[] b = a; int[] a = null; int[] b = null; a == b => false a == b => true a == b => true!

Default Equality The default equality for structs is simply the pairwise comparison between each of its fields. That is, two structs are equal if all of their fields are equal. Value-based field are compared by value. Reference fields are compared by reference (by default).

Testing for Equality There are actually five protocols or methods that you can use to test for equality. They may provide different results!!! Witness one says they are the same. Witness two says they are different.

Testing for Equality Operators for equality (== and !=). Recall that all operators are defined as static methods for a type. If there are different types on each side of the conditional, the compiler decides which type to use. All types have these operators defined. Unlike C++.

Testing for Equality The Object.Equals method exists for all types. It is virtual and hence can be overridden. Determines at run-time which type’s Equals method is called (Polymorphic). int x = 5; object y = 5; x == y => compile time error x.Equals(y) => true y.Equals(x) => true Note: x is boxed!

Testing for Equality Why have both of these? If a variable is null, calling Equals on it will result in a run-time exception. There is overhead associated with virtual function calls (and all function calls). The == operator can be statically inlined. Sometimes we want different behavior: We both own the same car (equals) but mine is not yours (not equals).

Testing for Equality There are also two static methods in the object class. static bool object.Equals(object o1, object o2); Simply calls o1.Equals if o1 != null. static bool object.ReferenceEquals(object o1, object o2); Since Equals can be overridden, this provides a forced reference equality check. Note: object.ReferenceEquals(5,5) = false!

The IEquatable interface Although the System.Object.Equals method can be applied to any type it will force a boxing of value types. The IEquatable interface allows value types which implement the interface to be called using a.Equals(b) without the boxing. Used as a generic constraint on user classes: class Test where T : IEquatable

Overriding Equality In general, do not change the default behavior (semantics). Implementing the default behavior for structs and the IComparable interface can avoid boxing and provide good performance improvements. Some immutable types may want different semantics: string, DateTime

Overriding Equality But what if I have Employee records and I want to check if two instances are equal? Do not build this into the Employee class. Use plug-in comparison classes to dynamically specify the behavior you want. This is what is used in the collection classes.

Equality Semantics If you override the semantics, then you must also override the hash code algorithm. There are several rules that you should make sure you follow for each of ==, Equals, and GetHashCode. If you override one of these you should probably override them all.

Overriding GetHashCode Rules for GetHashCode: Consistency – it must return the same value if called repeated on the same object. Even if you change the object!!!! Base it on an immutable value of the object. Equality – it must return the same value on two objects for which Equals returns true. Robust – it should not throw exceptions. Efficient – GetHashCode should generate a random distribution among all inputs.

Overriding GetHashCode For reference types, each instance has a unique hash-code based on the storage location. Can add it to a Collection (Dictionary), change the contents, and still get it back out using the hash code. If you override the hash code based on content rather than storage location, then the instance may need to be removed from the Dictionary, changed and added back.

Overriding GetHashCode Structs and value types are different, since they are never changed in-place, they are copied out, modified and copied back in. Hence this problem exists regardless of whether you override GetHashCode. struct X { public int x; } Dictionary test = new Dictionary (); X t1 = new X(); test[t1] = 5; t1.x = 3; test[t1] = 4; Adds a new entry to the dictionary

Overriding Equals Rules for overriding equals: An object should equal itself (reflexive). An object can not equal null Since it is an instance method call. Unless it is a Nullable type. Equality is commutative and transitive. a == b => b == a; b == c => a ==c; Equality operations are repeatable Equality is robust – no exceptions.

Overriding == and != You should always override == for value types for efficiency. You should never (or rarely) override it for reference types. Rules for overriding == a != b should be equal to !(a == b). It should have the same semantics as Equals. Hence the previous rules apply.

Example - Craps namespace OSU.Gambling.Craps { struct DiceRoll : IEquatable { internal DiceRoll(int die1, int die2) { this.die1 = die1; this.die2 = die2; } private int die1, die2;

Example - Craps namespace OSU.Gambling.Craps { struct DiceRoll : IEquatable { internal DiceRoll(int die1, int die2) { this.die1 = die1; this.die2 = die2; } private int die1, die2; I’ve never played this game. Requires two dice. I really want to control the creation, so make this constructor internal or private. Alas structs always have a public default constructor

Example - Craps public int Die1 { get { return die1+1; } } public int Die2 { get { return die2+1; } } Add one to allow for a default value of zero. Error checking should be done to ensure that die1 and die2 lie between 0 and 5.

Example - Craps public bool Equals(DiceRoll other) { return die1 == other.die1 && die2 == other.die2 || die1 == other.die2 && die2 == other.die1; } public override bool Equals(object other) { if (!(other is DiceRoll)) return false; return Equals((DiceRoll)other); // unbox the struct and compare. }

Example - Craps public static bool operator ==(DiceRoll die1, DiceRoll die2) { return die1.Equals(die2); } public static bool operator !=(DiceRoll die1, DiceRoll die2) { return !die1.Equals(die2); }

Example - Craps public override int GetHashCode() { return die1*11 + die2; } public override int GetHashCode() { if (die1 > die2) return 11 * die1 + die2; else return 11 * die2 + die1; }

Example - Craps public override int GetHashCode() { return die1*11 + die2; } public override int GetHashCode() { if (die1 > die2) return 11 * die1 + die2; else return 11 * die2 + die1; }

Example - Craps public static DiceRoll RollDice() { DiceRoll roll = new DiceRoll(); roll.die1 = random.Next(0,5); roll.die2 = random.Next(0,5); return roll; } private static readonly Random random; static DiceRoll() { random = new Random(System.DateTime.Now.Millisecond); }

Design Principle The previous code illustrated a good design principle you should follow: Ensure that zero is a valid state for all value types. Dice only have values from 1 to 6, so to make 0 a valid state we add one on the output.

Avoiding all of this The previous example can be made trivial and avoid all of this by simply requiring that die1 always be greater than die2 in the implementation. Control the creation. Works theoretically, but you may want the die to look more random for presentation purposes.

Example2 – Craps class public class DiceRoll : IEquatable { … public bool Equals(DiceRoll other) { if (other == null) return false; return (die1 == other.die1 && die2 == other.die2) || (die1 == other.die2 && die2 == other.die1); }

Example2 – Craps class public override bool Equals(object other) { if (other == null) return false; if (object.ReferenceEquals(this, other)) return true; if (this.GetType() != other.GetType()) return false; return Equals(other as DiceRoll); } …

Example2 – Craps class … public static DiceRoll RollDice() { return new DiceRoll(random.Next(0,5), random.Next(0,5)); } The only way to create a DiceRoll now.

Comparison (Sorting) Programming in C# Comparison (Sorting) CSE / ECE 668 Prof. Roger Crawfis

Comparison Comparing two instances of a type has many of the same properties and pitfalls as testing for equality. Equality is generally more fussy. Only two protocols for a type providing its own comparison: The IComparable interface The > and < operators

IComparable The IComparable and IComparable interfaces allow for sorting or ordering of a collection. They are used in the Array.Sort method. public interface IComparable { int CompareTo(T other); // -1 if this other } 5.CompareTo(7) => -1 “World”.CompareTo(“Hello”) => 1 32.CompareTo(8*4) => 0

IComparable Classes implementing IComparable are Values types like Int32, Double, DateTime, … The class Enum as base class of all enumeration types The class String Defines a type to be is-a IComparable.

The > and < operators Value types that have a clear context independent concept of less than and greater than should implement the operators. These are compiled statically into the code, making value types more efficient.

Changing Comparison Programming in C# Changing Comparison CSE 494R (proposed course for 459 Programming in C#) Prof. Roger Crawfis

IComparer IComparer is used to provide pluggable (or interchangable) comparisons. Used with a type, not part of the type. public interface IComparer { int Compare(object x, object y); // -1 if x y } IComparer implementations: Comparer, CaseInsensitiveComparer: for string comparisons

Custom IComparer Creation of table of strings: string[][] Table = { new string[] {"John", "Dow", "programmer"}, new string[] {"Bob", "Smith", "agent"}, new string[] {"Jane", "Dow", "assistant"}, new string[] {"Jack", "Sparrow", "manager"} }; Printing the table: foreach (string[] Row in Table) { Console.WriteLine(String.Join(", ", Row));String.Join }

Custom IComparer Comparer for single table (array) column: class ArrayComparer : IComparer where T : IComparable { private int m_Index; public ArrayComparer(int index) { this->index = index; } public int Compare(T[] x, T[] y) { return x[index ].CompareTo( y[index ] ); } Printing the table: Array.Sort(Employees, new ArrayComparer (2)); foreach (string[] Row in Employees) { Console.WriteLine(String.Join(", ", Row)); } Bob, Smith, agent Jane, Dow, assistant Jack, Sparrow, manager John, Dow, programmer

Custom IComparer Implement IComparable and IComparable public interface IComparable { int CompareTo(object obj); // -1: this obj } public interface IComparable { int CompareTo(T obj); // -1: this obj } class Fraction : IComparable, IComparable { private int n, d; public int CompareTo(object o) { return CompareTo((Fraction) o); } public int CompareTo(Fraction f) { return n*f.d – f.n*d }