CATEGORII DOCUMENTE |
An operator is a member that defines the meaning of an expression operator that can be applied to instances of the class. Operators are declared using operator-declarations:
operator-declaration:
attributesopt
operator-modifiers operator-declarator operator-body
operator-modifiers:
operator-modifier
operator-modifiers operator-modifier
operator-modifier:
public
static
extern
operator-declarator:
unary-operator-declarator
binary-operator-declarator
conversion-operator-declarator
unary-operator-declarator:
type operator overloadable-unary-operator ( type
identifier )
overloadable-unary-operator:
one
of
+ -
! ~ ++
-- true false
binary-operator-declarator:
type operator overloadable-binary-operator ( type
identifier , type
identifier )
overloadable-binary-operator:
one
of
+ -
* / %
& | ^
<< >> ==
!= > <
>= <=
conversion-operator-declarator:
implicit operator type
( type
identifier )
explicit operator type
( type
identifier )
operator-body:
block
;
There are three categories of overloadable operators: Unary operators (10.9.1), binary operators (10.9.2), and conversion operators (10.9.3).
The following rules apply to all operator declarations:
An operator declaration must include both a public and a static modifier.
When an operator declaration includes an extern modifier, the operator is said to be an external operator. Because an external operator provides no actual implementation, the operator-body of an external operator simply consists of a semi-colon.
For external operators, the operator-body consists simply of a semicolon. For all other operators, the operator-body consists of a block which specifies the statements to execute when the operator is invoked. The block of an operator must conform to the rules for value-returning methods described in 10.5.8.
The parameter(s) of an operator must be value parameters. It is an error for an operator declaration to specify ref or out parameters.
The signature of an operator (10.9.1, 10.9.2, 10.9.3) must differ from the signatures of all other operators declared in the same class.
All types referenced in an operator declaration must be at least as accessible as the operator itself (3.5.4).
Each operator category imposes additional restrictions, as described in the following sections.
Like other members, operators declared in a base class are inherited by derived classes. Because operator declarations always require the class or struct in which the operator is declared to participate in the signature of the operator, it is not possible for an operator declared in a derived class to hide an operator declared in a base class. Thus, the new modifier is never required, and therefore never permitted, in an operator declaration.
Additional information on unary and binary operators can be found in 7.2.
Additional information on conversion operators can be found in 6.4.
The following rules apply to unary operator declarations, where T denotes the class or struct type that contains the operator declaration:
A unary +, -, !, or ~ operator must take a single parameter of type T and can return any type.
A unary ++ or -- operator must take a single parameter of type T and must return type T.
A unary true or false operator must take a single parameter of type T and must return type bool.
The signature of a unary operator consists of the operator token (+, -, !, ~, ++, --, true, or false) and the type of the single formal parameter. The return type is not part of a unary operator's signature, nor is the name of the formal parameter.
The true and false unary operators require pair-wise declaration. An error occurs if a class declares one of these operators without also declaring the other. The true and false operators are described further in 7.16.
The following example shows an implementation and subsequent usage of operator++ for an integer vector class:
class IntVector
// read-only property
public int this[int index] // read-write indexer
public IntVector(int vectorLength)
public
static IntVector operator++(IntVector iv)
}
class Test
Note that the operator returns the value produced by adding 1 to the operand, just like the predefined version, as stated in 14.5.9 and 14.6.5.
A binary operator must take two parameters, at least one of which must have the class or struct type in which the operator is declared. A binary operator can return any type.
The signature of a binary operator consists of the operator token (+, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, or <=) and the types of the two formal parameters. The return type and names of the formal parameters are not part of a binary operator's signature.
Certain binary operators require pair-wise declaration. For every declaration of either operator of a pair, there must be a matching declaration of the other operator of the pair. Two operator declarations match when they have the same return type and the same type for each parameter. The following operators require pair-wise declaration:
operator == and operator !=
operator > and operator <
operator >= and operator <=
A conversion operator declaration introduces a user-defined conversion (6.4) which augments the pre-defined implicit and explicit conversions.
A conversion operator declaration that includes the implicit keyword introduces a user-defined implicit conversion. Implicit conversions can occur in a variety of situations, including function member invocations, cast expressions, and assignments. This is described further in 6.1.
A conversion operator declaration that includes the explicit keyword introduces a user-defined explicit conversion. Explicit conversions can occur in cast expressions, and are described further in 6.2.
A conversion operator converts from a source type, indicated by the parameter type of the conversion operator, to a target type, indicated by the return type of the conversion operator. A class or struct is permitted to declare a conversion from a source type S to a target type T provided all of the following are true:
S and T are different types.
Either S or T is the class or struct type in which the operator declaration takes place.
Neither S nor T is object or an interface-type.
T is not a base class of S, and S is not a base class of T.
From the second rule it follows that a conversion operator must convert either to or from the class or struct type in which the operator is declared. For example, it is possible for a class or struct type C to define a conversion from C to int and from int to C, but not from int to bool.
It is not possible to redefine a pre-defined conversion. Thus, conversion operators are not allowed to convert from or to object because implicit and explicit conversions already exist between object and all other types. Likewise, neither of the source and target types of a conversion can be a base type of the other, since a conversion would then already exist.
User-defined conversions are not allowed to convert from or to interface-types. This restriction in particular ensures that no user-defined transformations occur when converting to an interface-type, and that a conversion to an interface-type succeeds only if the object being converted actually implements the specified interface-type.
The signature of a conversion operator consists of the source type and the target type. (Note that this is the only form of member for which the return type participates in the signature.) The implicit or explicit classification of a conversion operator is not part of the operator's signature. Thus, a class or struct cannot declare both an implicit and an explicit conversion operator with the same source and target types.
In general, user-defined implicit conversions should be designed to never throw exceptions and never lose information. If a user-defined conversion can give rise to exceptions (for example, because the source argument is out of range) or loss of information (such as discarding high-order bits), then that conversion should be defined as an explicit conversion.
In the example
public
struct Digit
public static implicit operator byte(Digit d)
public static explicit operator Digit(byte
b)
}
the conversion from Digit to byte is implicit because it never throws exceptions or loses information, but the conversion from byte to Digit is explicit since Digit can only represent a subset of the possible values of a byte.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1011
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved