2. Operators and Casts Prepared By : Abed ElAzeem Bukhari What ‘s in this chapter? ➤ Operators in C# ➤ The idea of equality when dealing with reference and value types ➤ Data conversion between primitive data types ➤ Converting value types to reference types using boxing ➤ Converting between reference types by casting ➤ Overloading the standard operators for custom types ➤ Adding cast operators to custom types
7. operator shortcuts cont int x = 5; if (++x == 6) // true – x is incremented to 6 before the evaluation { Console.WriteLine("This will execute"); } if (x++ == 7) // false – x is incremented to 7 after the evaluation { Console.WriteLine("This won't"); }
8. Conditional operator condition ? true_value: false_value int x = 1; string s = x + " "; s += (x == 1 ? "man": "men"); Console.WriteLine(s);
9. The checked and unchecked operators byte b = 255; b++; Console.WriteLine(b.ToString()); ------------------------------------------------------- byte b = 255; checked { b++; } Console.WriteLine(b.ToString());
10. The checked and unchecked operators cont byte b = 255; unchecked { b++; } Console.WriteLine(b.ToString());
11. The is operator int i = 10; if (i is object) { Console.WriteLine("i is an object"); } int , like all C# data types, inherits from object ; therefore, the expression i is object will evaluate to true in this case, and the appropriate message will be displayed .
12. The as operator object o1 = "Some String"; object o2 = 5; string s1 = o1 as string; // s1 = "Some String" string s2 = o2 as string; // s2 = null
13. The sizeof operator Console.WriteLine(sizeof(int)); // This will display the number 4 , because an int is 4 bytes long. If you are using the sizeof operator with complex types (and not primitive types), you will need to block the code within an unsafe block as illustrated here: unsafe { Console.WriteLine(sizeof(Customer)); }
14. The typeof operator The typeof operator returns a System.Type object representing a specified type. For example, typeof(string) will return a Type object representing the System.String type. This is useful when you want to use reflection to find information about an object dynamically.
15. nullable Types and operators int? a = null; int? b = a + 4; // b = null int? c = a * 5; // c = null int? a = null; int? b = -5; if (a > = b) Console.WriteLine("a > = b"); else Console.WriteLine("a < b"); // However, when comparing nullable types, if only one of the operands is null , the comparison will always equate to false
18. Type Conversions byte value1 = 10; byte value2 = 23; byte total; total = value1 + value2; Console.WriteLine(total); When you attempt to compile these lines, you get the following error message: Cannot implicitly convert type ‘ int ’ to ‘ byte‘ The problem here is that when you add 2 bytes together, the result will be returned as an int , not as another byte
19. implicit Conversions byte value1 = 10; byte value2 = 23; long total; // this will compile fine total = value1 + value2; Console.WriteLine(total);
22. explicit Conversions These are some of the conversions that cannot be made implicitly: ➤ int to short — Data loss is possible. ➤ int to uint — Data loss is possible. ➤ uint to int — Data loss is possible. ➤ float to int — You will lose everything after the decimal point. ➤ Any numeric type to char — Data loss is possible. ➤ decimal to any numeric type — The decimal type is internally structured differently from both integers and floating-point numbers. ➤ int? to int — The nullable type may have the value null.
23. explicit Conversions These are some of the conversions that cannot be made implicitly: ➤ int to short — Data loss is possible. ➤ int to uint — Data loss is possible. ➤ uint to int — Data loss is possible. ➤ float to int — You will lose everything after the decimal point. ➤ Any numeric type to char — Data loss is possible. ➤ decimal to any numeric type — The decimal type is internally structured differently from both integers and floating-point numbers. ➤ int? to int — The nullable type may have the value null.
24. explicit Conversions cont long val = 30000; int i = (int)val; // A valid cast. The maximum int is 2147483647 long val = 3000000000; int i = (int)val; // An invalid cast. The maximum int is 2147483647 // I will be -1294967296 long val = 3000000000; int i = checked((int)val); // to check before casting Using casts, you can convert most primitive data types from one type to another; for example, in this code, the value 0.5 is added to price, and the total is cast to an int: double price = 25.30; int approximatePrice = (int)(price + 0.5); This gives the price rounded to the nearest dollar.
25. explicit Conversions cont ushort c = 43; char symbol = (char)c; Console.WriteLine(symbol); // The output is the character that has an ASCII number of 43, the + sign. --- int? a = null; int b = (int)a; // Will throw exception --- int i = 10; string s = i.ToString(); --- if you need to parse a string to retrieve a numeric or Boolean value, you can use the Parse() method supported by all the predefined value types: string s = “100”; int i = int.Parse(s) ; Console.WriteLine(i + 50); // Add 50 to prove it is really an int
26. boxing and unboxing int myIntNumber = 20; object myObject = myIntNumber; // Box the int int mySecondNumber = (int)myObject; // Unbox it back into an int
27.
28. The ReferenceEquals () Method SomeClass x, y; x = new SomeClass(); y = new SomeClass(); bool B1 = ReferenceEquals(null, null); // returns true bool B2 = ReferenceEquals(null,x); // returns false bool B3 = ReferenceEquals(x, y); // returns false because x and y // point to different objects
29. The virtual Equals() Method This method used usually by override it in your classes in order to Compare the instances of your class.
30. The static Equals() Method The static version of Equals() actually does the same thing as the virtual instance version. The difference is that the static version takes two parameters and compares them for equality.
34. overloading the Comparison operators ➤ == and != ➤ > and < ➤ > = and < = The C# language requires that you overload these operators in pairs. That is, if you overload == , you must overload != too; otherwise, you get a compiler error. In addition, the comparison operators must return a bool . If you overload == and !=, you must also override the Equals() and GetHashCode() methods inherited from System.Object; otherwise, you’ll get a compiler warning. The reasoning is that the Equals() method should implement the same kind of equality logic as the == operator.
39. implementing user-defined Casts cont Currency balance = new Currency(10,50); float f = balance; // We want f to be set to 10.5 To be able to do this, you need to define a cast. Hence, you add the following to your Currency definition: public static implicit operator float (Currency value) { return value.Dollars + (value.Cents/100.0f); }
40. Casts Between Classes public static explicit operator D(C value) { // and so on } public static explicit operator C(D value) { // and so on }
41. Casts Between Base and Derived Classes MyBase derivedObject = new MyDerived(); MyBase baseObject = new MyBase(); MyDerived derivedCopy1 = (MyDerived) derivedObject; // OK MyDerived derivedCopy2 = (MyDerived) baseObject; // Throws exception class DerivedClass: BaseClass { public DerivedClass( BaseClass rhs) { // initialize object from the Base instance } // etc.