COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in...

20
COMP10068 - Advanced Programming in .NET Week 5

Transcript of COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in...

Page 1: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

COMP10068 - Advanced Programming in .NET

Week 5

Page 2: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Operator OverloadingThere are various C# built-in types, such as

integer (int) and Boolean (bool), and there are also various operators that allow these data types to be manipulatedarithmetic: + - * / %comparisons: == != < <= > >=logical: && || ! & | ^

Using most of these operators with basic types is simple and intuitive

Using these operators with created classes will cause errors

Page 3: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Designing the Fraction ClassCreate a new type called Fraction to store

fractional numbers:Fraction first = new Fraction(1, 2); //create ½Fraction second = new Fraction(3, 4); //create ¾

Constructors take the first parameter as the numerator, and the second parameter as the denominator

To give the Fraction class all the functionality of the built-in types, there will be the need to perform arithmetic on instances of Fraction Add two Fractions, multiple them, etc Conversions to or from built-in types should also be

available

Page 4: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Each of these operations could be implemented using methods, but it’s not intuitively obvious:

Fraction sum = first.Add(second);

This is hard to readIt’s not how a user would immediately expect

addition to workIt doesn’t look like addition

It would be much better to be able to write:Fraction sum = first + second;

This is intuitive and easy to useIt is consistent with how built-in operators are added

Page 5: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Using the operator KeywordC# allows methods and constructors to be

overloadedIt also enables most operators to be

overloaded as well to make them sensitive to the context in which they are usedThe syntax is to write the keyword operator

followed by the operator to overloadOperators are public and static methodsThe return value of an operator represents the

result of an operationThe operator’s parameters are the operands

Page 6: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Define an addition operator for a Fraction class the same as any other method but with a difference:Instead of a method name, use operator+Addition is a binary operation, requiring two

operands, so the operator+ method will require two parameters of type Fraction

Addition has a result, requiring a return value of type Fractionpublic static Fraction operator +(Fraction lhs, Fraction rhs)

The parameters of lhs and rhs stand for left-hand side and right-hand side

Page 7: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

public class Fraction{ private int numerator; private int denominator;

//create a fraction by passing in the numerator and denominator public Fraction(int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; }

//return a string representation of the fraction public override string ToString() { string s = numerator.ToString() + "/" + denominator.ToString(); return s; }

Page 8: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

//overloaded + takes two fractions and returns their sum public static Fraction operator +(Fraction lhs, Fraction rhs) { //like fractions (shared denominators) can be added by adding their numerators if(lhs.denominator == rhs.denominator) return new Fraction(lhs.numerator + rhs.numerator, lhs.denominator);

//simplistic solution for unlike fractions is to cross-multiply: // 1/2 + 3/4 == ((1*4) + (3*2)) / (2*4) == 10/8 //this method does not reduce int firstProduct = lhs.numerator * rhs.denominator; int secondProduct = rhs.numerator * lhs.denominator;

return new Fraction(firstProduct + secondProduct, lhs.denominator * rhs.denominator); }}

Page 9: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

public class Tester{ public void Run() { Fraction f1 = new Fraction(3, 4); Console.WriteLine("f1: {0}", f1);

Fraction f2 = new Fraction(2, 4); Console.WriteLine("f2: {0}", f2);

Fraction f3 = f1 + f2; //test the overloaded addition operator Console.WriteLine("f1 + f2 = f3: {0}", f3);}

public static void Main() { Tester t = new Tester(); t.Run(); }}

Output would be:f1: 3/4f2: 2/4f1 + f2 = f3: 5/4

Page 10: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Creating Useful OperatorsOperator overloading can make code more

intuitive and allow them to be used similar to built-in typesHowever, they way they are used should make

senseOperators that don’t naturally follow their

traditional meanings will be confusingUse operator overloading when it makes an

application clearer than accomplishing the sameoperations with explicit method calls

Page 11: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Overload operators to perform the same function or similar functions on class objects as the operators perform on objects of simple types

At least one argument of an overloaded operator method must be a reference to an object of the class in which the operator is overloadedThis prevents programmers from changing

how operators work on simple types

Page 12: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

The Equals OperatorIt’s very common to overload the == operator to

determine whether two objects are equalWhat “equal” means is up to the programmer,

although the criteria should be reasonableTwo Employee objects might be equal if they have

the same name or perhaps if the same employee IDOverloading the == operator works the same way

as overloading any other operatorpublic static bool operator ==(Fraction lhs, Fraction rhs)

The == operator always returns a Boolean value (true or false)

Page 13: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

C# insists that if the equals operator is overloaded, then the not-equals (!=) operator must also be overloadedIt’s good programming practice to have the

inequality operator delegate its work to the equality operator

The != operator will return the opposite of the value of the == operator

Similarly, the less than (<) and greater than (>) operators must be paired as must the less than or equal to (<=) and greater than or equal to (>=) operators

Page 14: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

The Object class offers a virtual method called Equals()If the equals operator is overloaded, it is recommended

that the Equals() method also be overriddenOverriding the Equals() method allows the class to be

compatible with other .NET languages that do not overload operators but still support method overloading

That way, if the == operator can’t be used, the Equals() method is still availablepublic virtual bool Equals(object o)

Ensure that one Fraction object is being compared with another Fraction object, otherwise they cannot be equal

Page 15: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

//add these methods to the existing Fraction class

//test whether two Fractions are equal public static bool operator ==(Fraction lhs, Fraction rhs) { if(lhs.denominator == rhs.denominator && lhs.numerator == rhs.numerator) return true;

//code here to handle unlike Fractions return false; }

//delegates to operator == public static bool operator !=(Fraction lhs, Fraction rhs) { return !(lhs == rhs); //just the opposite of == }

//tests for same types, then delegates public override bool Equals(object o) { if(!(o is Fraction)) //objects have to be the same type to be equal return false;

return this == (Fraction)o; //cast the object as a Fraction and delegate to == }

Page 16: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

//can now add to the Run() method

Fraction f4 = new Fraction(5, 4);

if(f4 == f3) Console.WriteLine("f4: {0} == f3: {1}", f4, f3);

if(f4 != f2) Console.WriteLine("f4: {0} != f2: {1}", f4, f2);

if(f4.Equals(f3))

Console.WriteLine("{0}.Equals({1})", f4, f3);

Generates this output:f4: 5/4 == f3: 5/4f4: 5/4 != f2: 2/45/4.Equals(5/4)

Page 17: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Conversion OperatorsC# will convert an int to a long implicitly, but will

only allow a long to be converted to an int explicitlyThe conversion from int to long is implicit because

any int will fit into a longConversion from long to int must be explicit because

it is possible to lose information in the conversionIt would be useful for Fraction objects to be

converted to intrinsic types (such as int) and backGiven an int, implicit conversion to a Fraction can

be supported because any whole value is equal to that value over 1 (15 == 15/1)

Page 18: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

Given a Fraction, an explicit conversion back to an integer might be provided with the understanding that some information might be lostThe Fraction 9/4 might be converted to the integer

value 2 (truncating to the nearest whole number)To implement the conversion operator, the keyword operator is still used, but instead of a symbol to override, the type to be converted to is used instead

public static implicit operator Fraction(int theInt)

Use the implicit operator when the conversion is guaranteed to succeed and no information will be lost, otherwise, use the explicit operator instead

Page 19: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

//add these methods to the existing Fraction class

//overload the constructor to create a fraction from a whole number

public Fraction(int wholeNumber)

{

numerator = wholeNumber; //any whole number over 1 is a Fraction

denominator = 1;

}

//converts ints to Fractions implicitly

public static implicit operator Fraction(int theInt)

{

return new Fraction(theInt); //invoke constructor for a new Fraction

}

//convert Fractions to ints explicitly

public static explicit operator int(Fraction theFraction)

{

return theFraction.numerator / theFraction.denominator; //return an int

}

Page 20: COMP10068 - Advanced Programming in.NET Week 5. Operator Overloading There are various C# built-in types, such as integer ( int ) and Boolean ( bool ),

//can now add to the Run() method

Fraction f5 = f4 + 5; //implicit conversion of 5 to a Fraction Console.WriteLine("f4 + 5 = f5: {0}", f5);

int truncated = (int)f5; //explicit conversion of f5 to an int

Console.WriteLine("When you truncate f5 you get {0}", truncated);

Generates this output:f4 + 5 = f5: 25/4When you truncate f5 you get 6

The cast from an int to a Fraction is perfectly safe, so it can be implicit The implementation of this is to create a new Fraction object and to return it

The implicit cast operator causes the constructor to be invoked