C # Sharp experience ZZ Part 8 indexer and Operator Overloading

Source: Internet
Author: User
Li Jianzhong (cornyfield@263.net), Nanjing University of Posts and Telecommunications)
Http://www.microsoft.com/china/msdn/Archives/cornyfield/cornyfield8.asp

Index


C # Sharp experience

"Hello, world! "Program

C # BASIC Language Introduction

Basic Structure of Microsoft. NET platform

Class and Object

Constructor and destructor

Method

Domain and attribute

Indexer and operator overload

Array and string

Features and ing

Com interoperability with unmanaged programming and Exception Handling

Use C # to weave the future -- C # programming model Overview

Indexer

Indexer is a new type of class member introduced by C #. It allows objects to be referenced as conveniently and intuitively as arrays. The indexer is very similar to the attribute we mentioned earlier. However, the indexer can have a list of parameters and can only act on instance objects, rather than classes. The following is the design of a typical indexer. we ignore the specific implementation here.

 
Class myclass {public object this [int Index] {get {// retrieve data} set {// store data }}}

The indexer does not have a name like a property or method. The keyword "this" clearly expresses the features of objects referenced by the indexer. Like the attribute, the value keyword has the parameter transfer significance in the Set statement block. In fact, from the compiled il intermediate languageCodeThe above index is implemented as follows:

 
Class myclass {public object get_item (INT index) {// retrieve data} public void set_item (INT index, object Value) {// store data }}

Because our indexer is compiled into two methods: get_item (INT index) and set_item (INT index, object value, we cannot even declare the implementation of these two methods in the class that declares the Implementation of The indexer. the compiler will report an error for such behavior. In this way, the implicit implementation method can also be called, inherited, and other operations, which is the same as the method we implement. Understanding the underlying compilation implementation of c # language provides a good foundation for us to understand the behavior of C # indexer.

Like the method, the indexer has five access protection levels, four inheritance behavior modifiers, and an external indexer. There is no difference between these actions and the method. I will not repeat them here. The only difference is that the indexer cannot be static, which is easy to understand in the semantics of object reference. It is worth noting that base [e] should be used to access the parent class indexer when override is used to implement the indexer.

Like the implementation of attributes, the Data Type of the indexer is the return type of the get statement block and the type of the value keyword in the Set statement block.

The parameter list of The indexer is also worth noting. The "Index" feature makes it necessary for the indexer to have at least one parameter, which is placed in brackets after the this keyword. The parameters of the indexer can only be of the value type. They cannot be modified by REF (reference) or out (output. The data type of the parameter can be any data type in C. C # perform Polymorphism Analysis On The indexer based on different parameter signatures. All parameters in brackets can be referenced under get and set, while the value keyword can only be used as a passing parameter under set.

The following is a specific application example of the indexer. It is helpful for us to understand the design and application of the indexer.

Using system; Class bitarray {int [] bits; int length; Public bitarray (INT length) {If (length <0) throw new argumentexception (); bits = new int [(length-1)> 5) + 1]; this. length = length;} public int length {get {return length;} public bool this [int Index] {get {If (index <0 | index> = length) throw new indexoutofrangeexception (); elsereturn (BITS [index> 5] & 1 <index )! = 0;} set {If (index <0 | index> = length) throw new indexoutofrangeexception (); else if (value) bits [index> 5] | = 1 <index; elsebits [index> 5 ~ (1 <index) ;}} class test {static void main () {bitarray bits = new bitarray (10); For (INT I = 0; I <10; I ++) bits [I] = (I % 2) = 0; console. write (BITS [I] + "");}}

Compile and runProgramThe following output is displayed:

      True False

The above program provides you with an interface-friendly bool array through the use of the indexer, while greatly reducing the storage cost of the program. The indexer is usually used to provide a friendly access interface for the objects in the object container-that is why C # wraps the method into an indexer. In fact, we can see that the indexer has a large number of applications in the. NET Framework class library.

Operator overload

The operator is a member of expression operations between instance objects used to define classes in C. Like the indexer, operators are still a logical interface abstraction for method implementation. That is to say, operators are still called in the form of methods in the compiled il intermediate language code. Defining operator members in a class is also called Operator overloading. There are three types of overload operators in C #: unary operators, binary operators, and conversion operators. Not all operators can be reloaded. All three operators have corresponding reloaded operator sets, which are listed in the following table:

      Unary operator + -! ~ ++ -- True False
      Binary operator +-*/% & | ^ <>>=! ==<>=<=
      Implicit conversion () and explicit conversion ()

The overload operators must be public and static. Otherwise, compilation errors may occur, which is self-evident in the logical semantics of operators. The overload operator of the parent class will inherit from the quilt class, but this inheritance does not cover, hide, abstract, and so on. Virtual sealed override abstract cannot be modified on the overload operator. The parameter of the operator must be a value passing parameter. Here is a specific example:

Using system; Class Complex {Double R, V; // R + V ipublic complex (Double R, Double V) {This. R = r; this. V = V;} public static complex operator + (complex A, complex B) {return new complex (. R + B. r,. V + B. v);} public static complex operator-(complex a) {return new complex (-. r,-. v);} public static complex operator ++ (complex a) {double r =. R + 1; Double V =. V + 1; return new complex (R, V);} public void print () {console. write (R + "+" + V + "I") ;}} class test {public static void main () {complex A = new complex (3, 4 ); complex B = new complex (5, 6); complex c =-A; C. print (); complex d = a + B; D. print ();. print (); complex e = A ++;. print (); E. print (); complex F = ++ A;. print (); F. print ();}}

Compile the program and run it to get the following output:

      -3 +-4I 8 + 10i 3 + 4I 4 + 5I 3 + 4I 5 + 6i 5 + 6i

Here we implement a "+" binary operator, a "-" unary operator (negative value), and a "+ +" unary operator. Note that we have not made any changes to the passed parameters here-this is especially important when the parameters are referenced variables of the type, although the parameters of the overload operator can only be the value passing method. When returning values, we often need a new variable, except the true and false operators. This is especially important when the "++" and "--" operators are reloaded. That is to say, when we do a ++, We will discard the original a value, instead of the new value to! It is worth noting that the E value or F value in E = A ++ or F = ++ A has no connection with the return values of our overloaded operators! Their values only obtain the old or new values of A in front and back! It is not hard to understand the prefix and Postfix actions.

Operator Overloading imposes strict requirements on return values and parameter types. The unary operator has only one parameter. The Return Value Type and parameter type of the operators "++" and "--" must be the same as the type of the declared operator. Operator "+ -! ~" The parameter type of must be the same as that of the declared operator, and the return value type can be any. The parameter types of the true and false operators must be the same as those of the declared operator, while the return value must be bool and must be paired -- that is, it is wrong to declare only one of them, compilation errors may occur. Different parameter types may result in overload of operators with the same name -- in fact, this is a manifestation of method overload.

The binary operator parameters must be two, and at least one of the two parameters must be of the declared type. The return value type can be any. Three pairs of operators must also be paired with the declaration, which are "=" and "! = ","> "," <","> = ", And" <= ". It should be noted that the two parameters have different types. Although the types are the same but the order is different, the operators with the same name will be overloaded.

The conversion operators provide implicit and explicit conversions between different types. They are mainly used for method calls, transformation expressions, and value assignment operations. Conversion operators also have strict requirements on their parameter types (converted types) and return value types (converted types. The parameter type and return value type cannot be the same, and at least one of them must be of the same type as the defined operator. The conversion operator must be defined in any of the converted or converted types. Conversion operations defined by the system cannot be redefined. Neither of the two types is an object or an interface type, and there cannot be a direct or indirect inheritance relationship between the two. In these three cases, the system has been converted by default. Let's look at an example:

Using system; public struct digit {byte value; Public digit (byte value) {If (value <0 | value> 9) throw new argumentexception (); this. value = value;} public static implicit operator byte (digit d) {return D. value ;}public static explicit operator digit (byte B) {return New digit (B );}}

The preceding example provides implicit and explicit conversions between the digit and byte types. If the conversion from digit to byte is an implicit conversion, the conversion process will not throw an exception because of the loss of any information. The conversion from byte to digit is an explicit conversion. The conversion process may throw an exception due to information loss. In fact, this also reveals when implicit conversions are declared and when the design principles of conversions are declared. Both implicit and explicit conversions cannot be declared for the same parameter type. Implicit and explicit conversions do not need to be paired-although C # is recommended.

In fact, we can see that the interface operations provided to us by C # such as attributes, indexers, and operators are some form of logical abstract packaging of methods, it aims to provide a friendly and easy-to-use interface for the types of users we define-the functions they can implement through methods. After understanding the original design intention, we can make proper and correct use of these operations without causing misuse or misuse.

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.