Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

CSharp Bible (2002) [eng]-1

.pdf
Скачиваний:
42
Добавлен:
16.08.2013
Размер:
4.29 Mб
Скачать

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();

MyFirstPoint.X = 100;

MyFirstPoint.Y = 200;

MySecondPoint.X = 500;

MySecondPoint.Y = 750;

MyThirdPoint.X = 100;

MyThirdPoint.Y = 200;

if(MyFirstPoint == MySecondPoint) System.Console.WriteLine("MyFirstPoint and MySecondPoint are at

the

same coordinates."); else

System.Console.WriteLine("MyFirstPoint and MySecondPoint are

not at

the same coordinates.");

if(MyFirstPoint == MyThirdPoint) System.Console.WriteLine("MyFirstPoint and MyThirdPoint are at

the

same coordinates."); else

System.Console.WriteLine("MyFirstPoint and MyThirdPoint are not

at

the same coordinates.");

}

}

The Main() method defines three points:

MyFirstPoint, with coordinates of (100, 200)

MySecondPoint, with coordinates of (500, 750)

MyThirdPoint, with coordinates of (100, 200)

The method then uses the equality operator to determine whether the MyFirstPoint point and the MySecondPoint refer to the same coordinates. It then uses the equality operator to determine whether the MyFirstPoint point and the MyThirdPoint refer to the same coordinates.

Compiling and executing the code in Listing 10-7 results in the output shown in Figure 10-7.

Figure 10-7: Overloading the equality and inequality operators

The following pairs of operators must be overloaded together:

Equality and inequality

Less than and greater than

Less than or equal to and greater than or equal to

If you overload one of these pairs but not the other, the C# compiler issues an error message like the following:

error CS0216: The operator 'Point.operator ==(Point, Point)' requires a matching operator '!=' to also be defined

Overloadable Conversion Operators

You can also write operator overload methods that convert one type into another type. Your overload method can also define whether the C# compiler should treat the conversion as an implicit or explicit conversion.

If you need to define a new conversion operator in your class or structure, define a method with the following characteristics:

The keyword implicit if the conversion is to be treated as an implicit conversion, or the keyword explicit if the conversion is to be treated as an explicit conversion

The keyword operator

A type specifying the target type of the conversion

A parameter list specifying the source type of the conversion

Listing 10-8 defines an implicit conversion from a Point class object to a double. The double specifies the distance from the origin to the point, using the Pythagorean theorem.

Listing 10-8: Defining an Implicit Conversion

class Point

{

public int X; public int Y;

public static implicit operator double(Point RValue)

{

double Distance; double Sum;

Sum = (RValue.X * RValue.X) + (RValue.Y * RValue.Y); Distance = System.Math.Sqrt(Sum);

return Distance;

}

public static void Main()

{

double Distance;

Point MyPoint = new Point();

MyPoint.X = 100;

MyPoint.Y = 200;

Соседние файлы в предмете Программирование на C++