A random talk on C # specification

Source: Internet
Author: User
Tags arithmetic operators definition range
The specification continues as a ramble about the C # Language specification, and this month we will discuss the problem of operator overloading. Operator overloading (unless specified otherwise, the remainder of this column is simply "overloaded") is the ability to allow users to write expressions using user-defined types. It allows user-defined types to have the same functionality as predefined types.

For example, it is often necessary to write code similar to the following to add two numbers. It is clear that sum is two digits.

int i = 5;
int sum = i + j;

If you can write an expression of the same type using a user-defined type that represents a complex number, that's certainly best:

Complex i = 5;
Complex sum = i + j;

Operator overloading allows operators such as "+" to overload a user-defined type (that is, specify explicit meaning). If you do not overload, the user needs to write the following code:

Complex i = new Complex (5);
Complex sum = Complex.add (i, j);

This code works well, but the Complex type does not work as a predefined type in a language.

Everything has a specific time and place.
Operator overloading is an easily misunderstood language feature, and programmers treat it differently. Some people think that the programs that users write with this feature will be confusing and should not be attributed to the programming language. Others think it's a good feature that can be used anywhere.

Both of these ideas contain the right ingredients, but there are also deficiencies. Admittedly, operator overloading may lead to confusing programs written, but, in my experience, it is possible to write inexplicable code, even without operator overloading. In some cases, not using overloading can even make your code more confusing.

Those who use it indiscriminately, without any occasion, are "indeed" producing puzzling code.

Overloading is used in languages to simplify the concept of a user's class or structure. Operators can be overloaded only if they help to improve the readability of the code that the user writes. Please note that the inspection standard we are talking about is "clearer" rather than "shorter". Classes that use operator overloading almost always make the code shorter, but not every time it makes the code clearer (that is, more readable).

To illustrate this point, I have created multiple overload examples. You need to read the code carefully to see which operator is overloaded and what operation the overloaded operator performs.

Test
1
Bignum n1 = new Bignum ("123456789012345");
Bignum n2 = new Bignum ("11111");
Bignum sum = n1 + n2;

B
Matrix m1 = Loadmatrix ();
Matrix m2 = Loadmatrix ();
Matrix result = M1 * m2;

Iii
Dbrow row = query. Execute ();
while (!row. Done)
{
Viewer.add (row);
row++;
}

IV
Account current = Findaccount (Idnum);
current = 5;

Answers and discussions
1
In this example, the operation to be performed is obvious. This addition is simply adding predefined types, and everyone knows what operations are performed, so in this example, it makes sense to use operator overloading.

B
This example shows how matrices are multiplied. Conceptually, matrix multiplication is not exactly like conventional multiplication, but it is a well-defined operation, so anyone who understands the multiplication of matrices will not be surprised to see this overloaded operator.

Iii
In this example, the increment (+ +) operator is overloaded, which causes the database row to move forward to the next line. Anything related to a database row is unlikely to give us an idea of the true meaning of this increment, and the operations that this increment is going to perform are not so obvious.

In this example, the use of overloading does not make the code simpler. If we turn to the following code, the situation is much better:

Dbrow row = query. Execute ();
while (!row. MoveNext ())
{
Viewer.add (row);
}

IV
What does it mean to add things to employees? In this example, selecting is a good way to add it to the number of employees to register an employee. This is a bad operator overload usage.

Principle
The principle of when to overload is fairly straightforward. If the user wants to perform this operation, it should be overloaded.

Overloaded arithmetic operators
To overload the operators in C #, you specify the function to perform the operation. A function must be defined in the type involved in the operation, and at least one of the parameters belongs to that type. This prevents the addition of int or other strange things from being overloaded.

To demonstrate overloading, we will develop a vector. Vectors can be thought of as lines from the origin to a particular two-dimensional point. You can perform multiple operations on vectors. The following is a rough definition of this type:

struct Vector
{
float x;
Float y;

Public Vector (float x, float y)
{
this.x = x;
This.y = y;
}
}

To be actually used, the vector should support the following operations:

Get length
Multiply the vector by a number
Divide the vector by a number
Add two vectors
Subtract a vector from another vector
Calculate the dot product of two vectors
Our task is to determine how these operations should be implemented.

Length
There seems to be no meaningful operator for getting the length of the vector. Length does not change, so it makes sense to use it as a property:

public float Length
{
Get
{
Return ((float) math.sqrt (x * x + y * y));
}
}

Multiply/divide a vector by a number
Multiplying a vector by a number is a fairly common operation and is an operation that the user wants to implement. The following are the relevant code:

public static vector operator* (vector vector, float multiplier)
{
Return (new Vector (vector.x * multiplier,
VECTOR.Y * multiplier));
}

It should be noted that there are many interesting phenomena here. First, the operator is a static function, so it must get the value of two parameters and must return a new object in the result. The name of the operator is exactly "operator", followed by the operator to overload.

The code divided by a number is similar to the code above.

Add and subtract two vectors
This is a very common vector operation, so it is obvious that they should be overloaded.

public static vector operator+ (vector vector1, vector vector2)
{
Return (new Vector (vector1.x + vector2.x,
VECTOR1.Y + vector2.y));
}

The code for subtraction is very similar to the code above.

Calculate dot Product
The dot product of two vectors is a special operation defined for vectors, which cannot be found at all in the predefined types. In the equation, the dot product is represented by writing a point between two vectors, so it does not exactly match any of the existing operators. An interesting feature of dot product is that it gets two vector values, but only returns a simple number.

The user code is roughly the same regardless of whether the operation is overloaded. The first line shows the overloaded version in use, and the other lines show two alternate versions:

Double v1i = (Velocity * Center)/(T * t);
Double v1i = vector.dotproduct (velocity, center)/(T * t);
Double v1i = velocity. Dotproduct (center)/(T * t);

At this point, it is almost a judgment call. The class I wrote has overloaded the "*" Operator for dot-product operations, but I think it's not the most appropriate code to look back.

In the first example, velocity and center are vectors This is not very clear, so the dot product is the operation to perform this is not very clear (I am looking for an example of using it, I noticed this). The second example clearly illustrates what operations to perform, and I think the code in the example is the most appropriate.

The third example is OK, but I think the code will be clearer if the operation is not a member function.

public static double dotproduct (vector v1, vector v2)
{
Return (v1.x * v2.x + v1.y * v2.y);
}

C # and C + + overloads
Compared to C + +, C # allows overloading of fewer operators. There are two restrictions. First, member access, member invocations (that is, function calls), assignments, and new are not overloaded because these operations are defined by the runtime.

Second, operators such as "&&", "| |", "?:" and a composite assignment operator such as "+ =" cannot be overloaded because it makes the code incredibly complex and outweighs the gain.

Overloaded conversions
Let's go back to the original example:

Complex i = 5;
Complex sum = i + j;

Although we know how to overload the addition operator, we still need to think of ways to make the first statement work. This can be done by overloading the transformation.

Implicit and Explicit conversions
C # supports both implicit and explicit conversions. Implicit conversions are conversions that are always successful, and the reason for their success is usually that the range of the target type is equal to or greater than the range of the source type. The conversion from short to int is an implicit conversion. Implicit conversions can be part of an assignment statement:

Short svalue = 5;
Long lvalue = svalue;

Explicit conversions are those that can cause data loss or throw an exception. Therefore, explicit conversion requires coercion of type conversions:

Long lvalue = 5;
Short svalue = (short) lvalue;

When overloading a transformation, you should decide whether the conversion is implicit or explicit, but it should be understood that the implicit conversion model is secure, while explicit conversions are risky.

The conversion definition that converts an integer value of 5 to a complex number is as follows:

public static implicit operator Complex (int value)
{
Return (new Complex (value, 1.0));
}

This allows for an implicit conversion from int to Complex.

The interoperability of languages
The above is the case where operators are overloaded in C #. When it comes to other languages, things get a little complicated.

Operator overloading is not one of the features in the. NET common Language child set, which means that overloads will not be available in some languages. Therefore, it is important to provide alternatives that are not overloaded so that the same operations can still be performed in other languages. If your class defines the addition operator, it should also define the same method, using a name like ADD for naming.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.