C# Language Specification



Download 0,75 Mb.
bet391/524
Sana06.01.2022
Hajmi0,75 Mb.
#324842
1   ...   387   388   389   390   391   392   393   394   ...   524
Bog'liq
CSharp Language Specification

Conversion operators


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.

For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively. A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:


  • S0 and T0 are different types.

  • Either S0 or T0 is the class or struct type in which the operator declaration takes place.

  • Neither S0 nor T0 is an interface-type.

  • Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

For the purposes of these rules, any type parameters associated with S or T are considered to be unique types that have no inheritance relationship with other types, and any constraints on those type parameters are ignored.

In the example

class C {...}

class D: C


{
public static implicit operator C(D value) {...} // Ok

public static implicit operator C(D value) {...} // Ok

public static implicit operator C(D value) {...} // Error
}

the first two operator declarations are permitted because, for the purposes of §10.9.3, T and int and string respectively are considered unique types with no relationship. However, the third operator is an error because C is the base class of D.

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 directly 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 the source nor the target types of a conversion can be a base type of the other, since a conversion would then already exist.

However, it is possible to declare operators on generic types that, for particular type arguments, specify conversions that already exist as pre-defined conversions. In the example

struct Convertible


{
public static implicit operator Convertible(T value) {...}

public static explicit operator T(Convertible value) {...}


}

when type object is specified as a type argument for T, the second operator declares a conversion that already exists (an implicit, and therefore also an explicit, conversion exists from any type to type object).

In cases where a pre-defined conversion exists between two types, any user-defined conversions between those types are ignored. Specifically:


  • If a pre-defined implicit conversion (§6.1) exists from type S to type T, all user-defined conversions (implicit or explicit) from S to T are ignored.

  • If a pre-defined explicit conversion (§6.2) exists from type S to type T, any user-defined explicit conversions from S to T are ignored. Furthermore:

  • If T is an interface type, user-defined implicit conversions from S to T are ignored.

  • Otherwise, user-defined implicit conversions from S to T are still considered.

For all types but object, the operators declared by the Convertible type above do not conflict with pre-defined conversions. For example:

void F(int i, Convertible n) {


i = n; // Error
i = (int)n; // User-defined explicit conversion
n = i; // User-defined implicit conversion
n = (Convertible)i; // User-defined implicit conversion
}

However, for type object, pre-defined conversions hide the user-defined conversions in all cases but one:

void F(object o, Convertible n) {
o = n; // Pre-defined boxing conversion
o = (object)n; // Pre-defined boxing conversion
n = o; // User-defined implicit conversion
n = (Convertible)o; // Pre-defined unboxing conversion
}

User-defined conversions are not allowed to convert from or to interface-types. In particular, this restriction 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

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 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.



Download 0,75 Mb.

Do'stlaringiz bilan baham:
1   ...   387   388   389   390   391   392   393   394   ...   524




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish