Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
358,14 KB
Nội dung
• Unary minus • Logical negation • Bitwise complement operator • Prefix increment • Prefix decrement • The true keyword • The false keyword Overloading unary plus If you need to overload the unary plus, unary minus, negation, or bitwise complement operators in your class or structure, define a method with the following characteristics: • A return type of your choice • The keyword operator • The operator being overloaded • A parameter list specifying a single parameter of the type of class or structure containing the overloaded operator method As an example, revisit the Point class from Chapter 9. Suppose that you want to add a unary plus operator to the class that, when used, ensures that the coordinates of the point are both positive. This is implemented in Listing 10-1. Listing 10-1: Overloading the Unary Plus Operator class Point { public int X; public int Y; public static Point operator + (Point RValue) { Point NewPoint = new Point(); if(RValue.X < 0) NewPoint.X = -(RValue.X); else NewPoint.X = RValue.X; if(RValue.Y < 0) NewPoint.Y = -(RValue.Y); else NewPoint.Y = RValue.Y; return NewPoint; } public static void Main() { Point MyPoint = new Point(); MyPoint.X = -100; MyPoint.Y = 200; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); MyPoint = +MyPoint; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); } } The Main() method creates an object of type Point and sets its initial coordinates to (100, 200). It then applies the unary plus operator to the object and reassigns the result to the same point. It prints out the x and y coordinates to the console. The output of Listing 10-1 is shown in Figure 10-1. Figure 10-1: Overloading the unary operator The coordinates of the point have changed from (-100, 200) to (100, 200). The overloaded operator code is executed when the following statement is reached: MyPoint = +MyPoint; When this statement is reached, the unary plus operator overload for the Point class is executed. The expression on the right side of the equal sign is supplied as the parameter to the method. N ote The expression on the right-hand side of an assignment operator is often referred to as an rvalue, which is short for "right value." The expression on the left-hand side of an assignment operator is often referred to an lvalue, which is short for "left value." N aming the parameter in the operator overload method RValue makes it clear that the rvalue of the assignment is being passed in. This is just a naming convention and not a requirement. You are free to name your parameters using any legal identifier allowed by C#. This method creates a new Point object and then examines the coordinates of the supplied rvalue. If either of the parameters is negative, their values are negated, thereby turning them to positive values; and the now-positive values are assigned to the new point. Values that are not negative are assigned to the new point without any conversion. The new point is then returned from the method. The return value from the operator is used as the lvalue for the original statement. The return type of operator overloads for the unary plus, unary minus, negation, or bitwise complement operators does not have to be the same type as the rvalue. It can be any C# type that makes the most sense for the operator. Overloading unary minus Much like the unary plus, you can perform the unary minus override in the very same fashion. Listing 10-2 overrides the minus operator to handle the Point class. Listing 10-2: Overloading Unary Minus class Point { public int X; public int Y; public static Point operator - (Point RValue) { Point NewPoint = new Point(); if (RValue.X > 0) NewPoint.X = -(RValue.X); else NewPoint.X = RValue.X; if (RValue.Y > 0) NewPoint.Y = -(RValue.Y); else NewPoint.Y = RValue.Y; return NewPoint; } public static void Main() { Point MyPoint = new Point(); MyPoint.X = -100; MyPoint.Y = 200; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); MyPoint = -MyPoint; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); } } After you define your new Point operator, you simply define the action it should take when presented with a variable of type Point. Listing 10-2 declares the x coordinate as -100 and the y coordinate as 200. You print these values out to the console for visual verification and then use your overloaded operator. After your sample application has subtracted from the Point class, the resulting values are printed to the console window to indicate that it behaved as expected. Figure 10-2 is the output from Listing 10-2. Figure 10-2: Overloading unary minus So far, this chapter has covered unary minus and unary plus. These operators perform operations given one value — hence, the "unary." Other basic mathematical operators that can be used on one value are overloaded in the same fashion. The next section describes an operator of a different kind — the bitwise complement operator. Overloading bitwise complement The bitwise complement operator only has definitions for int, uint, long, and ulong. Listing 10-3 overloads it to work with the point class. Listing 10-3: Overloading the Bitwise Complement Operator class Point { public int X; public int Y; public static Point operator ~ (Point RValue) { Point NewPoint = new Point(); NewPoint.X = ~RValue.X; NewPoint.Y = ~RValue.Y; return NewPoint; } public static void Main() { Point MyPoint = new Point(); MyPoint.X = 5; MyPoint.Y = 6; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); MyPoint = ~MyPoint; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); } } The output of a bitwise complement operation doesn't become apparent until you view the hex results of the operation. Listing 10-3 generates the complement of the integer values 5 and 6. The output of this operation (shown in Figure 10-3) is -6 and -7, respectively. When you view the hex values of the input and output values, you soon realize what is actually happening. Figure 10-3: Overloading the bitwise complement Table 10-1: Input and Output Values for a Bitwise Complement Operation Input Output 0x0000000000000005 0xfffffffffffffffA 0x0000000000000006 0xfffffffffffffff9 Before you overload an operator, it is imperative that you fully understand how it works. Otherwise, you may end up with some unexpected results. Overloading the prefix increment If you need to overload the prefix increment or prefix decrement operators in your class or structure, define a method with the following characteristics: • A return type specifying the type of class or structure containing the overloaded operator method • The keyword operator • The operator being overloaded • A parameter list specifying a single parameter of the type of class or structure containing the overloaded operator method For an example, look at Listing 10-4. This class modifies the Point class to overload the prefix increment operator. The operator is overloaded to increment the x and y coordinates by one unit. Listing 10-4: Overloading the Prefix Increment class Point { public int X; public int Y; public static Point operator ++ (Point RValue) { Point NewPoint = new Point(); NewPoint.X = RValue.X + 1; NewPoint.Y = RValue.Y + 1; return NewPoint; } public static void Main() { Point MyPoint = new Point(); MyPoint.X = 100; MyPoint.Y = 200; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); MyPoint = ++MyPoint; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); } } Compiling and running the code in Listing 10-4 writes the following to the console: 100 200 101 201 Overloading the prefix decrement Now you'll examine how to overload the decrement operator to handle the Point class. Listing 10-5 contains the complete code listing to overload the operator much like that of the prefix increment operator just covered. Listing 10-5: Overloading the Prefix Decrement Operator class Point { public int X; public int Y; public static Point operator (Point RValue) { Point NewPoint = new Point(); NewPoint.X = RValue.X - 1; NewPoint.Y = RValue.Y - 1; return NewPoint; } public static void Main() { Point MyPoint = new Point(); MyPoint.X = 100; MyPoint.Y = 200; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); MyPoint = MyPoint; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); } } Figure 10-4: Output from compiling and running the code in Listing 10-4 Again, you pass in an x coordinate of 100 and a y coordinate of 200. Figure 10-5 contains the output of this program after your overload decrement operator has subtracted from both x and y. Figure 10-5: Overloading the prefix decrement operator Always assume the worst when overloading operators. It is always possible that the data being passed in may be bad, and you'll find that your overloaded function isn't equipped to handle the data. The previous examples don't bother to catch exceptions that may be thrown when bad or unexpected values are passed in. It's a good idea to play around with the functions and attempt to beef up the error trapping a bit. Overloading the true and false operators If you need to overload the true or false operators in your class or structure, define a method with the following characteristics: • A return type of bool • The keyword operator • The operator being overloaded • A parameter list specifying a single parameter of the type of class or structure containing the overloaded operator method For an example, look at Listing 10-6. It modifies the point class to evaluate to true whether the point is on the origin and to evaluate to false otherwise. Listing 10-6: Overloading the True and False Operators class Point { public int X; public int Y; public static bool operator true (Point RValue) { if((RValue.X == 0) && (RValue.Y == 0)) return true; return false; } public static bool operator false (Point RValue) { if((RValue.X == 0) && (RValue.Y == 0)) return false; return true; } public static void Main() { Point MyPoint = new Point(); MyPoint.X = 100; MyPoint.Y = 200; if(MyPoint) System.Console.WriteLine("The point is at the origin."); else System.Console.WriteLine("The point is not at the origin."); } } Overloading the true and false operators allows objects of the Point class to be used as Boolean expressions, as in the if statement. Because the MyPoint object is not at the origin, the object evaluates to false, as shown in Figure 10-6 . Figure 10-6: Overloading the true and false operators If either the true or false operators are overloaded for a class or structure, they both must be overloaded. If you overload one but not the other, the C# compiler issues an error message like the following: error CS0216: The operator 'Point.operator true(Point)' requires a matching operator 'false' to also be defined Overloadable Binary Operators Following is a list of the binary operators that can be overloaded: • Addition • Subtraction • Multiplication • Division • Remainder • AND • OR • Exclusive OR • Shift left • Shift right • Equality • Inequality • Greater than • Less than • Greater than or equal to • Less than or equal to If you need to overload any of the binary operators in your class or structure, define a method with the following characteristics: • A return type of your choice • The keyword operator • The operator being overloaded • A parameter list specifying two parameters, at least one of which must be of the type of class or structure containing the overloaded operator method Overloading binary operators enables you to be very flexible. You can use different parameters for the two parameters in the parameter list, which means that you can apply the operator to two values of different types if you wish. You can also use any available type as the return value from the overloaded operator. If you need to add together an object and a floating-point value and get a Boolean result, you can write an overloaded method as follows: static public bool operator + (Point MyPoint, float FloatValue) You can define multiple overloads of the same operator if you want, but only if the parameter lists use different types: static public bool operator + (Point MyPoint, float FloatValue) static public bool operator + (Point MyPoint, int IntValue) static public bool operator + (Point MyPoint, uint UIntValue) Listing 10-7 provides an example. It adds overloaded equality and inequality operators to the Point class. The operators return Boolean results that evaluate to true if two Point objects have the same coordinates; otherwise, the results evaluate to false. Listing 10-7: Overloading the Equality and Inequality Operators class Point { public int X; public int Y; public static bool operator == (Point Point1, Point Point2) { if(Point1.X != Point2.X) return false; if(Point1.Y != Point2.Y) return false; return true; } public override bool Equals(object o) { return true; } public override int GetHashCode() { return 0; } public static bool operator != (Point Point1, Point Point2) { if(Point1.X != Point2.X) return true; if(Point2.Y != Point2.Y) return true; return false; } public static void Main() { Point MyFirstPoint = new Point(); Point MySecondPoint = new Point(); Point MyThirdPoint = new Point(); [...]... abstract keyword when defining the class, you get an error from the C# compiler: error CS0513: 'Shape.GetArea ()' is abstract but it is contained in nonabstract class 'Shape' The C# compiler doesn't allow you to create objects from abstract classes If you try to create an object from an abstract class, the C# compiler issues an error: error CS0 144 : Cannot create an instance of the abstract class or interface... Inheritance In This Chapter Simple C# projects may use one or two classes However, you will most likely write many classes in your larger C# projects Many of these classes may have similar fields or methods, and it may make sense to share common code among a set of classes C# embraces the object-oriented concept of inheritance, which allows one class to inherit code from another class C# classes can inherit code... Console.WriteLine("Hit Enter to terminate "); Console.Read(); return 0; The NET Object Class All the classes in C# end up deriving from a class built into the NET Framework called object If you write a class in C# and do not define a base class for it, the C# compiler silently derives it from object Suppose that you write a C# class declaration without a class declaration, as follows: class Point2D This is equivalent... Overloaded C# does not enable you to redefine the behavior of the operators in the following list This is mainly for simplicity's sake The designers of the C# language wanted these operators kept simple, and to always perform their intended function; therefore, no overloading is allowed • • • • • Assignment Conditional AND Conditional OR Conditional The new, typeof, sizeof, and is keywords Summary C# enables... a sealed class, the C# compiler issues an error: error CS0509: 'Point3D' : cannot inherit from sealed class 'Point2D' Containment and Delegation Whereas inheritance is an IS-A relationship, containment is a HAS-A relationship A Burmese IS A cat (so you might want to inherit your Burmese class from your generic Cat class); whereas a Car HAS 4 tires (so your Car class may contain 4 Tire objects) The... the base class and the SingleSelectionListBox and the MultipleSelectionListBox classes are the derived classes Compiling with Multiple Classes Working with inheritance in C# means that you'll be working with more than one C# class C# is not picky about how those classes are arranged relative to your source files You can put all of your classes in a single source file, or you can put each class in a... The C# compiler turns the X and Y parameters into a parameter array for us and calls WriteLine() The X and Y parameters are of type integer, which, as you've already seen, is an alias for a structure called System.Int32 Because C# structures inherit from the NET object type, these variables inherit from the object type and can be used in the parameter array Literals, which are discussed in Chapter 4, ... System.Console.WriteLine("({0}, {1})", 100, 200); The C# compiler encounters the literals and boxes them both into objects The objects are supplied to the method call in the parameter array, and then the temporary objects are disposed of Take a look at the following statements: int MyValue = 123; object MyObject = MyValue; C# boxes the value of MyValue into the MyObject object C# also allows unboxing, which is simply... them Thanks to boxing by the C# compiler, the following code can actually work: string MyString; MyString = 123.ToString(); The C# compiler simply boxes the literal value 123 into an object and calls the ToString() method on that object Summary In object-oriented software development terminology, inheritance is used to describe a class that inherits members from a base class C# supports single inheritance,... class can be derived from a single base class C# does not support multiple inheritance, which is supported by some object-oriented languages to enable a class to be derived from more than one base class Base classes in C# are specified when a class is declared The base class identifier follows the name of the derived class when the derived class is declared C# enables class members to be associated with . Compiling with Multiple Classes Working with inheritance in C# means that you'll be working with more than one C# class. C# is not picky about how those classes are arranged relative. System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y); } } Figure 10 -4: Output from compiling and running the code in Listing 10 -4 Again, you pass in an x coordinate of 100 and a y coordinate of. Cannot Be Overloaded C# does not enable you to redefine the behavior of the operators in the following list. This is mainly for simplicity's sake. The designers of the C# language wanted