c# operator overloading and type conversions c#.net software development version 1.1
TRANSCRIPT
C# Operator Overloading and Type Conversions
C# .NET Software Development
Version 1.1
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 2
Operator Overloading Operators are static members of a class or struct One of the parameters must be of the enclosing
(class/struct) type Overloading operators does not affect their precedence or
associativity Overloading operators does not affect their order of operand
evaluation Only existing operators can be overloaded. You CANNOT
invent a new operator! Some operators require that you overload a counterpart
Example: if you overload operator ==, you should overload operator!=
Operators should generally return a new instance of the enclosing class
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 3
Operator Return types
C# Standard: “While it is possible for a user-defined operator to perform any
computation it pleases, implementations that produce results other than those that are intuitively expected are strongly discouraged. For example, an implementation of operator == should compare the two operands for equality and return an appropriate bool result.”
– C# Standard (p 126)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 4
C# OperatorsCategory Expression Description
Primary x.m Member access
x(...) Method and delegate invocation
x[...] Array and indexer access
x++ Post-increment
x-- Post-decrement
new T(...) Object, delegate creation and structure initialization
new T[...] Array creation
typeof(T) Obtain System.Type object of T
checked(x) Evaluate expression in checked context
unchecked(x) Evaluate expression in unchecked context
Unary +x Identity (Positive)
-x Negation
!x Logical negation
~x Bitwise negation
++x Pre-increment
--x Pre-decrement
(T)x Explicitly convert x to type T (Casting)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 5
Multiplicative x * y Multiplication
x / y Division
x % y Remainder
Additive x + y Addition, string concatenation, delegate combination
x – y Subtraction, delegate removal
Shift x << y Shift left
x >> y Shift right
Relational and type testing x < y Less than
x > y Greater than
x <= y Less than or equal
x >= y Greater than or equal
x is T Return true if x is a T, false otherwise
x as T Return x typed as T, or null if x is not a T
Equality x == y Equal
x != y Not equal
Logical AND x & y Integer bitwise AND, boolean logical AND
Logical XOR x ^ y Integer bitwise XOR, boolean logical XOR
Logical OR x | y Integer bitwise OR, boolean logical OR
Conditional AND x && y Evaluates y only if x is true
Conditional OR x || y Evaluates y only if x is false
Conditional x ? y : z Evaluates y if x is true, z if x is false
Lifted x ?? y
Assignment x = y Assignment
x op= y Compound assignment; supported operators are*= /= %= += -= <<= >>= &= ^= |=
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 6
Order of Operand Evaluation What’s the output?
using System;
class T{ static void Main() { int i = 6; Console.WriteLine(i++ + i++ * i); }}
(See OrderOfEvaluation Demo)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 7
Overloadable Operators Unary operators
+ - ! ~ ++ -- true false Binary Operators
+, -, *, /, %, &, &&, |, ||, ??, ^, <<, >>, ==,!=, >, <, >=, <= Compound assignment operators:
+=, -=, etc. (implicit overload) Binary arithmetic operators
+ - * / % ^ & | << >> Note: && and || are overloaded implicitly when you overload & and |
Binary comparison operators == != < <= > >= ??
Binary conditional operators true false
Conversions Any conversion (explicit or implicit) between the enclosing type and
another type.
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 8
Non-Overloadable Operators = . ?: -> new as is sizeof typeof checked
unchecked += -= *= /= %= &= |= ^= <<= >>= && ||
Note: Assignment operators are overloaded implicitly when you overload their binary counterpart
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 9
Unary Operators
Operators + - ! ~ ++ -- Operand must be of the enclosing
type
public static IntWrapper operator+(IntWrapper rhs){ return new IntWrapper(rhs._value);}
(See OperatorOverloading Demo)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 10
Unary Operators ++ and -- Remember C++ syntax?
public T operator++(); public T operator++(int);
In C#, one operator overload handles both cases Here’s how it works:
Whatever you return is the new value of your variable When a post operator is called, the old object (or reference) is
given to the expression When a pre operator is called, the new object (or reference) is
given to the expression In other words, the compiler just handles it!
Important: To get the behavior you expect, you must create a new object and return it If you modify the original value, it will affect the post operator
accordingly
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 11
Unary operator– int and T Example
publicpublic classclass T T{{ privateprivate intint i; i;
publicpublic staticstatic T T operatoroperator--(T t)--(T t) { { // Make new reference// Make new reference T ret = T ret = newnew T(); T(); ret.i = t.i-1;ret.i = t.i-1; returnreturn ret; ret; }}}}
publicpublic classclass int int{{ privateprivate intint i; i;
publicpublic staticstatic int int operatoroperator--(int t)--(int t) { { // Make new reference// Make new reference int ret = int ret = newnew int(); int(); ret.i = t.i-1;ret.i = t.i-1; returnreturn ret; ret; }}}}
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 12
Binary Operator Considerations At least one parameter must be of the enclosing type. Be aware of what you are returning
You will almost always want to return a new instance of the enclosing type
You may overload as many times as you like with different parameter types
You may return any type
No “ref” or “out” parameters
(See OperatorOverloadingBinary Demo)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 13
Binary Arithmetic Operators Operators + - * / % ^ & | << >> ?? At least one of the parameters must be of the enclosing
type
// Class1 + Class1public static Class1 operator+(Class1 lhs, Class1 rhs){ return new Class1(lhs.X + rhs.X);}
// Class1 + intpublic static Class1 operator+(Class1 lhs, int rhs){ return new Class1(lhs.X + rhs);}
// int + Class1public static Class1 operator+(int lhs, Class1 rhs){ return new Class1(rhs.X + lhs);}
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 14
Binary operators >> and << First parameter must be the enclosing type Second parameter must be an integer
// overloaded shift operatorpublic static Class2 operator<<(Class2 c2, int shl){
return new Class2(c2.i << shl);}
// this won't compilepublic static Class2 operator<<(Class2 c2, Class2 shl){
return new Class2(1000);}
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 15
Binary Comparison Operators Operators == != < <= > >= Should return bool
public static bool operator<(Class2 lhs, Class2 rhs){ return new Class2(lhs.i < rhs.i);}
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 16
Operators == and != Overloading == requires overloading the != why? Why have both == and .Equals() ?
Some .NET languages don’t allow operator overloading
You should define operator== in terms of .Equals()
It could be bad to do one and not the other
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 17
Binary Conditional Operators Operators true false
You must overload these if you want short-circuiting behavior and you have overloaded operator& and operator|
The true/false operators must be overloaded together
operator true: returns true if the class represents true, otherwise returns false
operator false: returns true if the class represents false, otherwise returns false
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 18
Using Operators && and ||
operator & and operator | are called conditionally when using && and || (respectively) operator & is only called if the first operand is true operator | is only called if first operand is false
When using && or || the first operand is evaluated using operator false or operator true (respectively) If you overload & and |, you cannot use && or || unless you
overload true and false
Why not just use conversion operator bool? The compiler won’t let you. (They were asleep when they
designed this)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 19
Conversion Operator bool
Allows your class to be used in conditional statements, including &&, ||, if, while, etc.
public static implicit operator bool(Class1 c){
return c.boolValue}
(See ShortCircuiting Demo Part 3)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 20
User-Defined Conversions “A conversion enables an expression of one type to be
treated as another type.” – C# Standard (p 113) A User-Defined Conversion between types T and S is
allowed when: S and T are different types Either S or T is the class or struct type in which the operator
declaration takes place Neither S nor T is an object or an interface-type T is not a base class of S, and S is not a base class of T
Conversions are allowed both to and from the enclosing type
You must state if the conversions is implicit or explicit Explicit conversions require a cast Implicit conversions don’t require a cast
(See UserDefinedConversion demo)
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 21
Finding the Best Conversion Finds the set of all classes and base classes involved Determines which user-defined conversions are applicable Finds the conversion for which both the operand and the
result match closest Searches for the best match of the operand type first Searches for the best match of the result last
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 22
Performing the conversion If required, converts the operand from its source type to the
operand type using standard conversions. Perform the user-defined conversion If required, convert the result to the target type using
standard conversions
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 23
Conversion Guidelines Conversions that would “narrow” your object should
be made explicit Conversions that would “widen” your object can be
made implicit
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 24
Conversion Vs. Operator If both an overloaded operator and a type conversion
exists between a user type and a standard type, the operator will be used and not the conversion.
Copyright © 2006-2011 by Dennis A. Fairclough all rights reserved. 25
What did you learn?
??