Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
10.1 Általános
Az átalakítás hatására egy kifejezés egy adott típusra konvertálódik, vagy annak minősül, az előbbi esetben az átalakítás a megjelenítés megváltozását vonhatja maga után. A konverziók lehetnek implicitek vagy explicitek, és ez határozza meg, hogy szükség van-e explicit leadásokra.
Példa: Például a típusról típusra
int
long
való átalakítás implicit, így a típuskifejezésekint
implicit módon kezelhetők típuskéntlong
. Az ellenkező átalakítás típusról típusralong
int
explicit, ezért explicit leadás szükséges.int a = 123; long b = a; // implicit conversion from int to long int c = (int) b; // explicit conversion from long to int
záró példa
Egyes konverziókat a nyelv határoz meg. A programok saját átalakításokat is meghatározhatnak (10.5. §).
A nyelv egyes konvertálásai kifejezésről típusra, mások típusról típusra vannak definiálva. A típusból való átalakítás az összes ilyen típusú kifejezésre vonatkozik.
Példa:
enum Color { Red, Blue, Green } // The expression 0 converts implicitly to enum types Color c0 = 0; // Other int expressions need explicit conversion Color c1 = (Color)1; // Conversion from null expression (no type) to string string x = null; // Conversion from lambda expression to delegate type Func<int, int> square = x => x * x;
záró példa
10.2 Implicit konverziók
10.2.1 Általános
A következő konverziók implicit konverziókként vannak besorolva:
- Identitásátalakítások (10.2.2. §)
- Implicit numerikus átalakítások (10.2.3. §)
- Implicit számbavételi konverziók (10.2.4. §)
- Implicit interpolált sztringátalakítások (10.2.5. §)
- Implicit referenciaátalakítások (10.2.8. §)
- Boxolási konverziók (§10.2.9)
- Implicit dinamikus átalakítások (10.2.10. §)
- Implicit típusú paraméterátalakítások (10.2.12. §)
- Implicit konstanskifejezés-konverziók (10.2.11. §)
- Felhasználó által definiált (beleértve a megemelt) implicit konverziókat (10.2.14.§)
- Névtelen függvényátalakítások (10.2.15.§)
- Metóduscsoport-átalakítások (10.2.15. §)
- Null literális konverziók (10.2.7. §)
- Implicit null értékű konverziók (10.2.6. §)
- Implicit átszámítások (10.2.13. §)
- Alapértelmezett konstans átalakítások (10.2.16. §)
- Implicit dobás konvertálása (10.2.17. §)
Az implicit konverziók számos helyzetben előfordulhatnak, beleértve a függvénytagok meghívását (12.6.6. §), az öntvénykifejezéseket (12.9.7. §) és a hozzárendeléseket (12.21. §).
Az előre definiált implicit konverziók mindig sikeresek, és soha nem okoznak kivételeket.
Megjegyzés: A megfelelően megtervezett, felhasználó által definiált implicit konverzióknak ezeket a jellemzőket is meg kell jelennie. végjegyzet
Átalakítás céljából a típusok object
és dynamic
az identitás átalakíthatóak (10.2.2. §).
A dinamikus átalakítások (10.2.10.§) azonban csak a típuskifejezésekre dynamic
vonatkoznak (8.2.4. §).
10.2.2 Identitásátalakítás
Az identitásátalakítás bármilyen típusból ugyanarra a típusra vagy futásidőben egyenértékű típusra konvertálódik. Ennek az átalakításnak az egyik oka az, hogy egy típus T
vagy egy típuskifejezés T
önmagára T
konvertálható legyen. A következő identitáskonverziók léteznek:
- Között
T
ésT
, minden típushozT
. - Bármely referenciatípus között
T
ésT?
azok esetébenT
. - Között
object
ésdynamic
. - Az azonos aritású összes rekordtípus és a megfelelő létrehozott
ValueTuple<...>
típus között, ha az identitásátalakítás az egyes megfelelő elemtípusok párja között létezik. - Az azonos általános típusból létrehozott típusok között, ahol az egyes megfelelő típusargumentumok között identitáskonverzió áll fenn.
Példa: A következő a harmadik szabály rekurzív jellegét szemlélteti:
(int a , string b) t1 = (1, "two"); (int c, string d) t2 = (3, "four"); // Identity conversions exist between // the types of t1, t2, and t3. var t3 = (5, "six"); t3 = t2; t2 = t1; var t4 = (t1, 7); var t5 = (t2, 8); // Identity conversions exist between // the types of t4, t5, and t6. var t6 =((8, "eight"), 9); t6 = t5; t5 = t4;
A csuplok
t1
t2
t3
típusainak két eleme van: egyint
és egystring
. A tuple elemtípusok maguk is lehetnek a rekordok, például at4
,t5
ést6
a . Az identitáskonvertálás a megfelelő elemtípusok párjai között létezik, beleértve a beágyazott csuplokat is, ezért identitáskonvertálás létezik a tuplesekt4
t5
típusai ést6
a .záró példa
Minden identitásátalakítás szimmetrikus. Ha identitáskonvertálás létezik, T₁
T₂
akkor az identitáskonvertálás innen a T₂
másikra T₁
történik. Két típus az identitáskonvertálás, ha az identitáskonvertálás két típus között létezik.
Az identitásátalakítás a legtöbb esetben futásidőben nincs hatással. Mivel azonban a lebegőpontos műveletek a típusuk által előírtnál nagyobb pontossággal végezhetők el (8.3.7. §), eredményeik hozzárendelése a pontosság csökkenését eredményezheti, és az explicit öntöttek garantáltan csökkentik a pontosságot a típus által előírtakhoz képest (12.9.7. §).
10.2.3 Implicit numerikus konverziók
Az implicit numerikus konverziók a következők:
- Feladó
sbyte
,short
,int
,long
float
,double
vagydecimal
. - Feladó
byte
,short
,ushort
int
,uint
,long
,ulong
,float
, ,double
vagydecimal
. - Feladó
short
,int
,long
,float
double
, vagydecimal
. - Feladó
ushort
,int
,uint
long
,ulong
,float
,double
vagydecimal
. - From
int
,long
, ,float
ordouble
.decimal
- Feladó
uint
,long
,ulong
,float
double
, vagydecimal
. -
long
Fromfloat
, ,double
ordecimal
. -
ulong
Fromfloat
, ,double
ordecimal
. - Feladó
char
,ushort
,int
uint
,long
,ulong
,float
,double
, vagydecimal
. -
float
-tóldouble
-ig.
int
Az , , uint
, long
vagy ulong
float
a forrásból vagy long
a forrásból ulong
double
történő átalakítások pontosságvesztést okozhatnak, de soha nem okoznak nagyságvesztést. A többi implicit numerikus konverzió soha nem veszt el semmilyen információt.
Nincsenek előre definiált implicit átalakítások a char
típusra, így a többi integráltípus értékei nem konvertálódnak automatikusan a char
típusra.
10.2.4 Implicit számbavételi konverziók
Az implicit számbavételi átalakítás lehetővé teszi, hogy egy constant_expression (12.23. §) bármilyen egész számtípussal és nullával bármilyen enum_type és nullable_value_type alakítsa át, amelynek mögöttes típusa egy enum_type. Az utóbbi esetben az átalakítás kiértékelése az alapul szolgáló enum_type való átalakítással és az eredmény körbefuttatásával történik (8.3.12. §).
10.2.5 Implicit interpolált sztringátalakítások
Az implicit interpolált sztringátalakítás lehetővé teszi egy interpolated_string_expression (12.8.3
Az átalakítás alkalmazásakor a sztringértékek nem az interpolált sztringből lesznek összeállítva. Ehelyett létrejön egy példány System.FormattableString
a 12.8.3.
10.2.6 Implicit null értékű konverziók
Az implicit null értékű konverziók azok a null értékű konverziók (10.6.1. §), amelyek implicit előre definiált konverziókból származnak.
10.2.7 Null literális konverziók
Implicit átalakítás létezik a literáltól bármilyen null
referenciatípusig vagy null értékű értéktípusig. Ez az átalakítás null hivatkozást hoz létre, ha a céltípus hivatkozástípus, vagy az adott null értékű érték null értéke (8.3.12. §).
10.2.8 Implicit referenciaátalakítások
Az implicit referenciakonvertálások a következők:
- Bármely reference_type és
object
dynamic
. -
S
származik.T
- Bármely bármely
S
, a megadottT
implementálásokS
. -
S
származik.T
-
egy elemtípussal
S
Sᵢ
T
, feltéve, hogy az alábbiak mindegyike igaz:-
S
ésT
csak elemtípusban különbözik. Más szóval,S
ésT
ugyanannyi dimenzióval rendelkezik. - Implicit referenciakonvertálás létezik a helyről
Sᵢ
a másikraTᵢ
.
-
- Az egydimenziós tömbtípustól
S[]
System.Collections.Generic.IList<T>
a ,System.Collections.Generic.IReadOnlyList<T>
és azok alapillesztőiig, feltéve, hogy implicit identitás vagy referencia-átalakítás történik a helyrőlS
a másikraT
. - A array_type
System.Array
és az általa implementálandó felületektől kezdve. - A delegate_type
System.Delegate
és az általa implementálandó felületektől kezdve. - A null literáltól (6.4.5.7. §) bármilyen referenciatípusig.
- Bármely reference_typereference_type
T
, ha implicit identitással vagy hivatkozási átalakítással rendelkezik egy , ésT₀
identitásátalakítássalT₀
rendelkezik. - Bármely reference_type illesztő- vagy delegálttípusba
T
, ha implicit identitással vagy hivatkozási átalakítással rendelkezik egy interfész- vagy delegálástípusraT₀
, ésT₀
variancia-átalakítható (18.2.3.3.3. §)-rólT
. - A típusparamétereket tartalmazó implicit konverziók, amelyek ismerten referenciatípusok. A típusparamétereket tartalmazó implicit konverziókról a 10.2.12 .
Az implicit referenciakonvertálások olyan reference_types közötti konverziók, amelyek bizonyítottan mindig sikeresek, ezért futásidőben nem igényelnek ellenőrzést.
Az implicit vagy explicit konverziókra való hivatkozás soha ne módosítsa a konvertált objektum hivatkozási identitását.
Megjegyzés: Más szóval, bár a hivatkozás konvertálása megváltoztathatja a hivatkozás típusát, soha nem változtatja meg a hivatkozott objektum típusát vagy értékét. végjegyzet
10.2.9 Boxing konverziók
A boxing konverzió lehetővé teszi, hogy egy value_type implicit módon reference_type alakítsa át. A következő boxing konverziók léteznek:
- Bármely value_type a típushoz
object
. - Bármely value_type a típushoz
System.ValueType
. - A enum_type típusától a típusig
System.Enum
. - A non_nullable_value_type által implementált interface_type bármilyen non_nullable_value_type.
- Az non_nullable_value_type
- Bármely non_nullable_value_type, amely
I
egy másik vált, és variancia-átalakítható (I₀
. §)I₀
lesz . - Az nullable_value_type minden olyan reference_type, ahol a nullable_value_type alapjául szolgáló típusról a reference_type való boxing átalakításra kerül sor.
- Olyan típusparaméterből, amelyről ismert, hogy nem referenciatípus, a 10.2.12.
A nem null értékű értékek dobozolása egy objektumpéldány kiosztásából és az adott példányba való másolásából áll.
Egy nullable_value_type értékének dobozolása null hivatkozást eredményez, ha az null érték (HasValue
hamis), vagy a mögöttes érték kibontásának és dobozolásának eredménye.
Megjegyzés: Az ökölvívás folyamata minden értéktípus esetében elképzelhető egy boxosztály megléte szempontjából. Fontolja meg például egy
struct S
interfészI
implementálását, amelynek neve boxosztályS_Boxing
.interface I { void M(); } struct S : I { public void M() { ... } } sealed class S_Boxing : I { S value; public S_Boxing(S value) { this.value = value; } public void M() { value.M(); } }
A típus
v
értékénekS
megadása mostantól a kifejezésnew S_Boxing(v)
végrehajtásából és az eredményül kapott példány visszaadásából áll, az átalakítás céltípusának értékeként. Így az állításokS s = new S(); object box = s;
a következőhöz hasonlónak tekinthető:
S s = new S(); object box = new S_Boxing(s);
A fent leírt képzelt boxtípus valójában nem létezik. Ehelyett egy dobozos típusnak
S
a futtatókörnyezet típusaS
van, a futtatókörnyezet típusának ellenőrzéseis
pedig az operátorral értéktípussal, mint a jobb operandus ellenőrzi, hogy a bal operandus a jobb operandus dobozos verziója-e. Például,int i = 123; object box = i; if (box is int) { Console.Write("Box contains an int"); }
a következő kimenetet adja ki:
Box contains an int
A boxing konverzió azt jelenti, hogy másolatot készít a dobozolt értékről. Ez eltér a tekinthető . Például:
struct Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } class A { void M() { Point p = new Point(10, 10); object box = p; p.x = 20; Console.Write(((Point)box).x); } }
a 10 értéket adja ki a konzolon, mert az implicit boxing művelet, amely a hozzárendelés
p
box
során következik be, ap
másolást okozza. HaPoint
ehelyett deklaráltákclass
volna, a 20 érték kimenet lenne, mertp
box
ugyanarra a példányra hivatkozna.A boxosztály analógiája nem használható hasznos eszközként a boxolás fogalmi működésének szemléltetésére. A specifikáció által leírt viselkedés és a boxolás pontosan ilyen módon történő implementálásából eredő viselkedés között számos apró különbség van.
végjegyzet
10.2.10 Implicit dinamikus konverziók
Implicit dinamikus átalakítás létezik egy dinamikus típusú kifejezésből bármilyen típusba T
. Az átalakítás dinamikusan kötődik a 12.3.3. §-hoz, ami azt jelenti, hogy a kifejezés futásidejű típusától az implicit konverziót a program T
futásidőben kéri. Ha nem található átalakítás, a rendszer futásidejű kivételt eredményez.
Ez az implicit átalakítás látszólag sérti a 10.2. § elején azt a tanácsot, hogy az implicit átalakítás soha nem okozhat kivételt. Azonban nem maga az átalakítás, hanem az átalakítás megtalálása okozza a kivételt. A futásidejű kivételek kockázata a dinamikus kötés használatában rejlik. Ha az átalakítás dinamikus kötése nem kívánatos, a kifejezés először konvertálható object
a kívánt típusra, majd a kívánt típusra.
Példa: Az alábbiak az implicit dinamikus konverziókat szemléltetik:
object o = "object"; dynamic d = "dynamic"; string s1 = o; // Fails at compile-time – no conversion exists string s2 = d; // Compiles and succeeds at run-time int i = d; // Compiles but fails at run-time – no conversion exists
A hozzárendelések implicit dinamikus konverziókat
s2
i
alkalmaznak, ahol a műveletek kötése futási időre felfüggesztve van. Futásidőben implicit konverziókat keres a rendszer a (d
) futásidejűstring
típusától a céltípusig. A konvertálás a következőre történik,string
de nem a következőreint
: .záró példa
10.2.11 Implicit konstanskifejezés-konverziók
Az implicit konstanskifejezés-átalakítás a következő konverziókat teszi lehetővé:
- A constant_expression (12.23.§)
int
típussásbyte
alakítható,byte
short
ushort
uint
feltéve,ulong
hogy a constant_expression értéke a céltípus tartományán belül van. - Egy constant_expression
long
típussáulong
alakítható át, feltéve, hogy a constant_expression értéke nem negatív.
10.2.12 Típusparamétereket tartalmazó implicit konverziók
A referenciatípusnak ismert type_parameterT
(15.2.5.§) a következő implicit referenciakonverziók (10.2.8. §) léteznek:
- A tényleges alaposztálytól
T
C
a bármely alaposztályigT
C
, valamintT
C
a . - A
T
interface_typeI
- A
T
megadottU
típusparamétertőlT
függU
(15.2.5. §).Megjegyzés: Mivel
T
ismert, hogy referenciatípus, a hatókörönT
belül a futtatási idő típusaU
mindig referenciatípus lesz, még akkor is, haU
nem ismert, hogy referenciatípus a fordítási időpontban. végjegyzet - A null literáltól (6.4.5.7. §) a T-be.
A 15.2.5 hivatkozási típusnak nem ismert type_parameter T
esetében a fordítási időpontban T
a következő konverziók minősülnek boxing konverziónak (10.2.9. §). Futásidőben, ha T
értéktípusról van szó, a konvertálás boxing konverzióként lesz végrehajtva. Futtatáskor, ha T
referenciatípusról van szó, az átalakítás implicit referenciakonverzióként vagy identitásátalakításként lesz végrehajtva.
- A tényleges alaposztálytól
T
C
a bármely alaposztályigT
C
, valamintT
C
a .Megjegyzés:
C
az egyik típusSystem.Object
System.ValueType
, vagySystem.Enum
(más névenT
referenciatípus) lesz. végjegyzet - A
T
interface_typeI
Olyan type_parameterT
esetében, amelyről ismert, hogy nem referenciatípus, implicit átalakítás történik a megadott T
U
típusparaméterre T
U
. Futásidőben, ha T
értéktípus, és U
referenciatípus, akkor a konvertálás boxing konverzióként lesz végrehajtva. Futásidőben, ha mindkettő T
és U
értéktípus is, akkor T
és U
szükségszerűen ugyanaz a típus, és nem történik átalakítás. Futásidőben, ha T
referenciatípus, akkor U
szükségképpen referenciatípus is, és az átalakítás implicit referenciaátalakításként vagy identitásátalakításként történik (15.2.5. §).
Az alábbi további implicit konverziók léteznek egy adott típusparaméterhez T
:
- Referenciatípusra
T
S
, ha implicit átalakítással rendelkezik egy referenciatípusraS₀
, ésS₀
identitásátalakítássalS
rendelkezik. Futtatáskor a konvertálás ugyanúgy történik, mint aS₀
konvertálás. - Kapcsolódási típusról illesztőtípusra
T
, ha implicit átalakítással rendelkezik egy illesztőtípusraI
I₀
, ésI₀
variancia-átalakítható (I
. §). Futásidőben, haT
értéktípusról van szó, a konvertálás boxing konverzióként lesz végrehajtva. Ellenkező esetben az átalakítás implicit referenciakonvertálásként vagy identitásátalakításként lesz végrehajtva.
A szabályok minden esetben biztosítják, hogy az átalakítás boxing konverzióként történjen, ha és csak akkor, ha futásidőben az átalakítás értéktípusról hivatkozástípusra történik.
10.2.13 Implicit tuple konverziók
Implicit átalakítás létezik egy rekordkifejezésről E
egy rekordtípusra T
, ha E
ugyanolyan aritása van, és T
az implicit konverzió az egyes elemektől E
a megfelelő elemtípusig létezik a következőben T
: . Az átalakítás a megfelelő T
típusú példány System.ValueTuple<...>
létrehozásával és az egyes mezők balról jobbra történő inicializálásával, a megfelelő rekordelem-kifejezés E
kiértékelésével, a talált implicit átalakítás megfelelő elemtípusára T
való konvertálásával és a mező eredményével való inicializálásával történik.
Ha a rekordkifejezés egyik elemneve nem egyezik meg a rekordtípus megfelelő elemnevével, figyelmeztetést kell kiadni.
Példa:
(int, string) t1 = (1, "One"); (byte, string) t2 = (2, null); (int, string) t3 = (null, null); // Error: No conversion (int i, string s) t4 = (i: 4, "Four"); (int i, string) t5 = (x: 5, s: "Five"); // Warning: Names are ignored
A ,
t1
ést2
t4
mind érvényes deklarációkt5
, mivel implicit konverziók léteznek az elemkifejezésektől a megfelelő elemtípusokig. A deklarációt3
érvénytelen, mert nincs konvertálás a következőrenull
int
: . A deklarációt5
figyelmeztetést okoz, mert a rekordkifejezés elemnevei eltérnek a rekordtípusban szereplőtől.záró példa
10.2.14 Felhasználó által definiált implicit konverziók
A felhasználó által definiált implicit átalakítás egy opcionális standard implicit konverzióból áll, amelyet egy felhasználó által definiált implicit konverziós operátor végrehajtása követ, amelyet egy másik opcionális standard implicit konverzió követ. A felhasználó által definiált implicit konverziók kiértékelésére vonatkozó pontos szabályokat a 10.5.4.
10.2.15 Névtelen függvénykonverziók és metóduscsoport-átalakítások
A névtelen függvények és metóduscsoportok nem rendelkeznek típusok önmagukban és önmagukban, de implicit módon delegált típusokká alakíthatók. Emellett egyes lambda-kifejezések implicit módon kifejezésfatípusokká alakíthatók. A névtelen függvények konvertálását részletesebben a §10.7-ben, a metóduscsoport-átalakításokat pedig a 10.8.
10.2.16 Alapértelmezett konstanskonverziók
Implicit átalakítás létezik egy default_literal (12.8.21. §)-ból bármilyen típusra. Ez az átalakítás a kikövetkzett típus alapértelmezett értékét (§9.3) állítja elő.
10.2.17 Implicit dobás konverziók
Bár a dobókifejezések nem rendelkeznek típussal, implicit módon bármilyen típussá konvertálhatók.
10.3 Explicit konverziók
10.3.1 Általános
A következő konverziók explicit konverziókként vannak besorolva:
- Minden implicit átalakítás (10.2. §)
- Explicit numerikus átalakítások (10.3.2. §)
- Explicit enumerálási átalakítások (10.3.3.3.)
- Explicit null értékű átalakítások (10.3.4. §)
- Explicit átszámítások (10.3.6. §)
- Explicit referenciaátalakítások (10.3.5. §)
- Explicit felületátalakítások
- Átalakítások kicsomagolása (10.3.7. §)
- Explicit típusú paraméterek konvertálása (10.3.8. §)
- Felhasználó által definiált explicit konverziók (10.3.9. §)
Explicit átalakítások történhetnek a öntött kifejezésekben (12.9.7. §).
Az explicit konverziók készlete tartalmazza az összes implicit konverziót.
Megjegyzés: Ez például lehetővé teszi, hogy explicit leadás legyen használva, ha implicit identitáskonvertálás van, hogy kényszerítse egy adott metódus túlterhelésének kiválasztását. végjegyzet
Az explicit konverziók, amelyek nem implicit konverziók, olyan konverziók, amelyek nem bizonyíthatók mindig sikeresnek, az olyan konverziók, amelyekről ismert, hogy elveszítik az információkat, és a különböző típusú tartományok közötti konverziók eléggé eltérőek ahhoz, hogy explicit jelölést érdemeljenek.
10.3.2 Explicit numerikus konverziók
Az explicit numerikus átalakítások olyan numeric_type egy másik numeric_type való konvertálásai, amelyeknél az implicit numerikus átalakítás (10.2.3. §) még nem létezik:
- Feladó
sbyte
,byte
,ushort
,uint
ulong
, vagychar
. - Feladó
byte
vagysbyte
char
. - Feladó
short
,sbyte
,byte
,ushort
uint
,ulong
vagychar
. - From
ushort
,sbyte
, ,byte
orshort
.char
- Feladó
int
,sbyte
,byte
short
,ushort
,uint
,ulong
vagychar
. - Feladó
uint
,sbyte
,byte
,short
ushort
,int
vagychar
. - Feladó
long
,sbyte
,byte
short
,ushort
,int
,uint
,ulong
, vagychar
. - Feladó
ulong
,sbyte
,byte
short
,ushort
,int
,uint
,long
, vagychar
. -
char
Fromsbyte
, ,byte
orshort
. - Feladó
float
,sbyte
,byte
,short
ushort
,int
,uint
,long
,ulong
char
vagydecimal
. - Feladó
double
,sbyte
,byte
,short
ushort
,int
,uint
,long
,ulong
,char
,float
, vagydecimal
. - Feladó
decimal
,sbyte
,byte
,short
ushort
,int
,uint
,long
,ulong
,char
,float
, vagydouble
.
Mivel a explicit konverziók tartalmazzák az összes implicit és explicit numerikus konverziót, minden numeric_type átalakítható bármely más numeric_type egy öntött kifejezéssel (12.9.7. §).
A explicit numerikus konverziók esetleg elveszítik az információkat, vagy kivételeket okozhatnak. A explicit numerikus átalakítás a következőképpen lesz feldolgozva:
- Az integráltípusból egy másik integráltípusba történő átalakítás esetében a feldolgozás a túlcsordulás ellenőrzési környezetétől (12.8.20. §) függ, amelyben az átalakítás végbemegy:
-
checked
Egy környezetben az átalakítás akkor sikeres, ha a forrásoperandus értéke a céltípus tartományán belül van, de aSystem.OverflowException
forrás operandus értéke kívül esik a céltípus tartományán. -
unchecked
Egy kontextusban az átalakítás mindig sikeres lesz, és az alábbiak szerint halad.- Ha a forrástípus nagyobb a céltípusnál, akkor a forrásértéket csonkolja a rendszer az "extra" legfontosabb bitek elvetésével. Az eredmény ezután a céltípus értékeként lesz kezelve.
- Ha a forrástípus mérete megegyezik a céltípus méretével, akkor a forrásérték a céltípus értékeként lesz kezelve
-
- Az integrál típusú átalakítás
decimal
esetén a forrásérték nullára kerekítve lesz a legközelebbi integrálértékre, és ez az integrál érték lesz az átalakítás eredménye. Ha az eredményként kapott integrálérték kívül esik a céltípus tartományán, a függvény egySystem.OverflowException
értéket ad. - Az integrált típusból
float
vagydouble
az integrált típusba történő átalakítás esetében a feldolgozás attól a túlcsordulás-ellenőrzési környezettől függ (12.8.20.§), amelyben az átalakítás történik:- Egy ellenőrzött környezetben az átalakítás a következőképpen halad:
- Ha az operandus értéke NaN vagy végtelen, az a
System.OverflowException
lesz. - Ellenkező esetben a forrás operandus nulla felé kerekítve lesz a legközelebbi integrál értékre. Ha ez az integrál érték a céltípus tartományán belül van, akkor ez az érték az átalakítás eredménye.
- Ellenkező esetben egy
System.OverflowException
van dobva.
- Ha az operandus értéke NaN vagy végtelen, az a
- A nem ellenőrzött környezetben az átalakítás mindig sikeres lesz, és az alábbiak szerint halad.
- Ha az operandus értéke NaN vagy végtelen, az átalakítás eredménye a céltípus meghatározatlan értéke.
- Ellenkező esetben a forrás operandus nulla felé kerekítve lesz a legközelebbi integrál értékre. Ha ez az integrál érték a céltípus tartományán belül van, akkor ez az érték az átalakítás eredménye.
- Ellenkező esetben az átalakítás eredménye a céltípus meghatározatlan értéke.
- Egy ellenőrzött környezetben az átalakítás a következőképpen halad:
-
double
float
A konvertálás során az érték adouble
legközelebbifloat
értékre lesz kerekítve. Ha azdouble
érték túl kicsi ahhoz, hogy az értékkéntfloat
legyen jelölve, az eredmény nullává válik ugyanazzal a jellel, mint az érték. Ha az érték nagyságadouble
túl nagy ahhoz, hogy az értékkéntfloat
legyen jelölve, az eredmény végtelenné válik ugyanazzal a jellel, mint az érték. Ha azdouble
érték NaN, az eredmény szintén NaN. - A forrásértéket
float
ábrázolássádouble
alakítjuk át,decimal
decimal
és szükség esetén a legközelebbi számra kerekítve (8.3.8. §).- Ha a forrásérték túl kicsi ahhoz, hogy az értékként
decimal
legyen jelölve, az eredmény nullává válik, megőrizve az eredeti érték előjelét, hadecimal
támogatja az aláírt nulla értékeket. - Ha a forrásérték mérete túl nagy ahhoz, hogy végtelenként
decimal
legyen jelölve, akkor az eredmény az eredeti érték előjelét megőrző végtelenség, ha a tizedesjegy támogatja a végteleneket; ellenkező esetben a System.OverflowException függvényt dobják ki. - Ha a forrásérték NaN, akkor az eredmény NaN, ha a tizedesvessző támogatja a NaN-eket; ellenkező esetben a System.OverflowException parancs ki lesz dobva.
- Ha a forrásérték túl kicsi ahhoz, hogy az értékként
- A másikról a másikra
decimal
való átalakításfloat
esetén azdouble
érték a legközelebbiredecimal
vagydouble
értékre lesz kerekítve.float
Ha a forrásérték mérete túl nagy ahhoz, hogy a céltípusban szerepeljen, vagy ez az érték végtelen, az eredmény a végtelenség, amely megőrzi az eredeti érték jelét. Ha a forrás értéke NaN, az eredmény NaN. Bár ez az átalakítás elveszítheti a pontosságot, soha nem okoz kivételt.
Megjegyzés: A
decimal
típus nem szükséges a végtelenség vagy a NaN értékek támogatásához, de ezt megteheti; tartománya kisebb lehet, mint a tartományfloat
ésdouble
, de ez nem garantált. Végtelen vagy NaN-értékek nélküli ábrázolások eseténdecimal
, és a tartomány kisebb, mintfloat
a végtelen vagy a NaN közötti átalakításdecimal
float
eredménye, vagydouble
soha nem lesz. végjegyzet
10.3.3 Explicit enumerálási konverziók
A explicit enumerálási konverziók a következők:
- A
sbyte
,byte
,short
,ushort
,int
uint
long
ulong
char
float
,double
, vagydecimal
bármely enum_type. - Bármely
sbyte
byte
short
ushort
, ,int
uint
,long
, ,ulong
, ,char
, ,float
, vagy .double
- Bármely enum_type bármely más enum_type.
A két típus közötti explicit számbavételi átalakítás úgy történik, hogy a részt vevő enum_type az adott enum_type alapul szolgáló típusaként kezeli, majd implicit vagy explicit numerikus konverziót hajt végre az eredményül kapott típusok között.
Példa: A mögöttes típusával rendelkező
E
int
E
-rólbyte
-ra történő konvertálás explicit numerikus átalakításként történik (§10.3.2)int
-rőlbyte
- ésbyte
-rőlE
-ra történő átalakítás implicit numerikus átalakításként (§10.2.3) történikbyte
-rólint
- ra . záró példa
10.3.4 Explicit null értékű konverziók
Az explicit null értékű konverziók azok a null értékű konverziók (10.6.1. §), amelyek explicit és implicit előre definiált konverziókból származnak.
10.3.5 Explicit referenciakonvertálások
Az explicit referenciakonvertálások a következők:
- Objektumtól bármely más reference_type.
- Bármely class_type
S
, a megadottT
alaposztály.S
- Bármely class_type
S
, feltéveT
, hogy nem lezárt, és feltéveS
, hogy nem implementálódik .S
- Bármely interface_type
S
, feltéveT
, hogy nem lezárt vagy biztosítottT
eszközök .T
-
A megadott interface_type
S
T
nem származik .S
-
egy elemtípussal
S
Sᵢ
T
, feltéve, hogy az alábbiak mindegyike igaz:-
S
ésT
csak elemtípusban különbözik. Más szóval,S
ésT
ugyanannyi dimenzióval rendelkezik. - Explicit referenciakonvertálás létezik a helyről
Sᵢ
a .-raTᵢ
.
-
- Az általa implementálható felületektől
System.Array
kezdve a array_type. - Az egydimenziós és annak alapfelületei között, feltéve, hogy az identitásátalakítás vagy a explicit referenciakonvertálás a cél
S[]
feléSystem.Collections.Generic.IList<T>
történik. - From
System.Collections.Generic.IList<S>
,System.Collections.Generic.IReadOnlyList<S>
, and their base interfaces to a single-dimensional array typeT[]
, feltéve, hogy van egy identitásátalakítás vagy explicit hivatkozás konvertálása A-rólS
T-be. - Az általa implementálandó felületekről és felületekről
System.Delegate
bármely delegate_type. - Referenciatípusról referenciatípusra, ha explicit hivatkozási átalakítással rendelkezik referenciatípusra
S
, ésT
az identitás áttér a referenciatípusraS
T₀
T₀
.T₀
T
- Referenciatípusról
S
felületre vagy delegálási típusraT
, ha explicit referencia-átalakítás történik interfész- vagy delegálástípusraS
T₀
, ésT₀
variancia-átalakíthatóT
T
vagy variancia-átalakíthatóT₀
a 18.2.3.3.3. - A feladótól a helyig
D<S₁...Sᵥ>
D<T₁...Tᵥ>
D<X₁...Xᵥ>
általános delegálási típus,D<S₁...Sᵥ>
nem kompatibilis vagy azonosD<T₁...Tᵥ>
a következő típusparaméterekkelXᵢ
D
:- Ha
Xᵢ
invariáns, akkorSᵢ
megegyezik aTᵢ
. - Ha
Xᵢ
kovariant, akkor identitáskonvertálás, implicit referenciakonvertálás vagy explicit referenciakonvertálás történikSᵢ
.Tᵢ
- Ha
Xᵢ
a contravariant, akkorSᵢ
azonosTᵢ
vagy mindkét referenciatípus.
- Ha
- A típusparamétereket tartalmazó explicit konverziók, amelyek ismerten referenciatípusok. A típusparamétereket tartalmazó explicit átalakításokról a 10.3.8.
Az explicit referenciakonvertálások olyan reference_types közötti átalakítások, amelyek futásidejű ellenőrzéseket igényelnek a helyességük érdekében.
Ahhoz, hogy az explicit referenciaátalakítás futásidőben sikeres legyen null
, a forrásoperandus értéke vagy a forrásoperandus által hivatkozott objektum típusa olyan típus, amely implicit referenciaátalakítással konvertálható a céltípusra (10.2.8. §). Ha egy explicit hivatkozás konvertálása meghiúsul, System.InvalidCastException
a függvény egy hibát ad.
Megjegyzés: Az implicit vagy explicit referenciaátalakítások soha nem módosítják a hivatkozás értékét (8.2.1. §), csak annak típusát; a hivatkozott objektum típusát és értékét sem módosítja. végjegyzet
10.3.6 Explicit tuple konverziók
Explicit átalakítás létezik egy rekordkifejezésből E
tuple típusúra T
, ha E
ugyanolyan aritása van, és T
az implicit vagy explicit konverzió az egyes elemektől E
a megfelelő elemtípusig létezik a következőben T
: . Az átalakítás a megfelelő T
típusú példány System.ValueTuple<...>
létrehozásával és az egyes mezők balról jobbra történő inicializálásával, a megfelelő rekordelem-kifejezés E
kiértékelésével, a talált explicit átalakítás megfelelő elemtípusára T
való konvertálásával és a mező eredményével való inicializálásával történik.
10.3.7 A konvertálások leválasztása
A beérkezett üzenetek törlése lehetővé teszi, hogy egy reference_type explicit módon value_type alakítsa át. A következő unboxing konverziók léteznek:
- A típustól
object
a value_type. - A típustól
System.ValueType
a value_type. - A típustól
System.Enum
a enum_type. - A interface_type megvalósító non_nullable_value_type interface_type.
- Az interface_type
I
minden olyan non_nullable_value_type, ahol egy interface_type a non_nullable_valueI₀
és az identitás konvertálásaI
a következőreI₀
történik: - Az interface_type
I
minden olyan non_nullable_value_type típusra, amelyre létezik unboxing konverzió egy interface_typeI₀
-ről a non_nullable_value_type típusra, és ahol vagyI₀
variancia szempontjából konvertálhatóI
-re, vagyI
variancia szempontjából konvertálhatóI₀
-ra (§18.2.3.3). - Az reference_type minden olyan nullable_value_type, ahol a reference_type-ről a nullable_value_type mögöttes non_nullable_value_typevaló váltása nem történik meg.
- Olyan típusparaméterből, amelyről ismert, hogy nem értéktípus, olyan típusra, amelynél az átalakítást a 10.3.8.
A non_nullable_value_type való kicsomagolási művelet először ellenőrzi, hogy az objektumpéldány az adott non_nullable_value_type dobozos értéke-e, majd kimásolja az értéket a példányból.
Ha egy nullable_value_type nem adhatja meg a nullable_value_type null értékét, ha a forrásoperandus null
az, vagy ha az objektumpéldányt a nullable_value_type alapjául szolgáló típusba csomagolja, akkor a burkolt eredmény.
Megjegyzés: A 10.2.9. §-ban leírt képzeletbeli boxing osztályra hivatkozva az objektummezők value_type
S
való nem dobozos konvertálása a kifejezés((S_Boxing)box).value
végrehajtásából áll. Így az állításokobject box = new S(); S s = (S)box;
fogalmilag megfelel a
object box = new S_Boxing(new S()); S s = ((S_Boxing)box).value;
végjegyzet
Ahhoz, hogy egy adott non_nullable_value_type való váltás futásidőben sikeres legyen, a forrásoperandus értékének az adott non_nullable_value_type egy dobozolt értékére kell hivatkoznia. Ha a forrás operandus null
egy System.NullReferenceException
dobás. Ha a forrásoperandus egy nem kompatibilis objektumra mutató hivatkozás, System.InvalidCastException
a rendszer egy hibát ad vissza.
Ahhoz, hogy egy adott nullable_value_type való váltás futásidőben sikeres legyen, a forrásoperandus értéke null értékű, vagy a nullable_value_type mögöttes non_nullable_value_type egy dobozolt értékére való hivatkozás. Ha a forrásoperandus egy nem kompatibilis objektumra mutató hivatkozás, System.InvalidCastException
a rendszer egy hibát ad vissza.
10.3.8 Típusparamétereket tartalmazó explicit konverziók
A referenciatípusnak ismert type_parameterT
(15.2.5. §) a következő explicit referenciaátalakítások (10.3.5. §) léteznek:
- A tényleges alaposztálytól a kezdő és a kezdő osztályig
C
T
.T
C
T
- Bármely interface_type.
T
- Minden
T
interface_type -
,
U
amelytőlT
függT
(U
. §).Megjegyzés: Mivel
T
ismert, hogy referenciatípus, a hatókörönT
belül a futtatási idő típusa mindig referenciatípus lesz, még akkor is, haU
nem ismert, hogy referenciatípus a fordítási időpontban. végjegyzet
Olyan type_parameterT
esetében, amelyről ismert, hogy nem referenciatípus (15.2.5. §), a fordítási időpontban T
a következő átalakítások minősülnek nem beérkezett konverzióknak (10.3.7. §). Futtatáskor, ha T
értéktípusról van szó, a rendszer a konvertálást nem beérkezett üzenetekre való konvertálásként hajtja végre. Futtatáskor, ha T
referenciatípusról van szó, a konvertálás explicit referenciakonvertálásként vagy identitásátalakításként lesz végrehajtva.
- A tényleges alaposztálytól a kezdő és a kezdő osztályig
C
T
.T
C
T
Megjegyzés: A C az egyik típus
System.Object
,System.ValueType
vagySystem.Enum
(más névenT
referenciatípus). végjegyzet - Bármely interface_type.
T
Olyan type_parameterT
esetében, amely nem ismert referenciatípus (15.2.5. §), a következő explicit átalakítások léteznek:
-
T
feltéve, hogy még nem történt implicit átalakítás a fájlból.I
Ez az átalakítás implicit boxing átalakításból áll (10.2.9.§),T
object
amelyet egy explicit hivatkozási átalakításobject
I
követ. Futtatáskor, haT
értéktípusról van szó, a rendszer boxing konverzióként hajtja végre az átalakítást, amelyet explicit referenciakonvertálás követ. Futásidőben, haT
referenciatípusról van szó, a konvertálás explicit referenciakonvertálásként lesz végrehajtva. - A megadott
U
típusparamétertőlT
T
függU
(15.2.5. §). Futtatáskor, haT
értéktípus, ésU
referenciatípus, a rendszer a konvertálást nem beérkezett üzenetekre való konvertálásként hajtja végre. Futásidőben, ha mindkettőT
ésU
értéktípus is, akkorT
ésU
szükségszerűen ugyanaz a típus, és nem történik átalakítás. Futásidőben, haT
referenciatípus, akkorU
szükségképpen referenciatípus is, és az átalakítás explicit referenciakonvertálásként vagy identitásátalakításként történik.
A szabályok minden esetben biztosítják, hogy az átalakítás akkor és csak akkor legyen megadva, ha futásidőben az átalakítás hivatkozástípusról értéktípusra történik.
A fenti szabályok nem teszik lehetővé a nem betanított típusparaméter közvetlen explicit konvertálását nem interfész típusúra, ami meglepő lehet. Ennek a szabálynak az az oka, hogy megakadályozza a félreértéseket, és egyértelművé tegye az ilyen átalakítások szemantikáját.
Példa: Fontolja meg a következő deklarációt:
class X<T> { public static long F(T t) { return (long)t; // Error } }
Ha a közvetlen explicit átalakítás
t
long
engedélyezve lett volna, könnyen előfordulhat, hogy ezX<int>.F(7)
vissza fog térni7L
. Ez azonban nem lenne így, mert a standard numerikus konverziókat csak akkor veszik figyelembe, ha a típusok ismerten numerikusak kötési időpontban. A szemantika egyértelművé tétele érdekében a fenti példát inkább meg kell írni:class X<T> { public static long F(T t) { return (long)(object)t; // Ok, but will only work when T is long } }
Ez a kód most lefordítva lesz, de a végrehajtás
X<int>.F(7)
futásidőben kivételt eredményezne, mivel a dobozosint
elemeket nem lehet közvetlenül átalakítani .long
záró példa
10.3.9 Felhasználó által definiált explicit konverziók
A felhasználó által definiált explicit átalakítás egy opcionális standard explicit konverzióból áll, amelyet egy felhasználó által definiált implicit vagy explicit konverziós operátor végrehajtása követ, amelyet egy másik opcionális standard explicit konverzió követ. A felhasználó által definiált explicit konverziók kiértékelésére vonatkozó pontos szabályokat a 10.5.5.
10.4 Standard konverziók
10.4.1 Általános
A standard konverziók olyan előre definiált átalakítások, amelyek egy felhasználó által meghatározott átalakítás részeként történhetnek.
10.4.2 Standard implicit konverziók
A következő implicit konverziók standard implicit konverziókként vannak besorolva:
- Identitásátalakítások (10.2.2. §)
- Implicit numerikus átalakítások (10.2.3. §)
- Implicit null értékű konverziók (10.2.6. §)
- Null literális konverziók (10.2.7. §)
- Implicit referenciaátalakítások (10.2.8. §)
- Boxolási konverziók (§10.2.9)
- Implicit konstanskifejezés-konverziók (10.2.11. §)
- Típusparamétereket tartalmazó implicit konverziók (10.2.12.§)
A standard implicit konverziók kifejezetten kizárják a felhasználó által definiált implicit konverziókat.
10.4.3 Standard explicit konverziók
A standard explicit konverziók mind standard implicit konverziók, valamint azoknak az explicit konverzióknak a részhalmaza, amelyek esetében ellentétes standard implicit konverzió létezik.
Megjegyzés: Más szóval, ha egy szabványos implicit átalakítás típusról típusra
A
B
létezik, akkor a standard explicit átalakítás típusról típusraA
B
és típusról típusraB
A
létezik. végjegyzet
10.5 Felhasználó által definiált konverziók
10.5.1 Általános
A C# lehetővé teszi, hogy az előre definiált implicit és explicit konverziókat felhasználó által meghatározott konverziókkal bővítse. A felhasználó által definiált átalakításokat a konverziós operátorok (15.10.4.§) osztály- és szerkezettípusokban történő deklarálásával vezetik be.
10.5.2 Felhasználó által engedélyezett konverziók
A C# csak bizonyos felhasználó által meghatározott konverziók deklarálását teszi lehetővé. Nem lehet újradefiniálást elvégezni egy már meglévő implicit vagy explicit átalakításon.
Egy adott forrástípus és céltípus S
esetében – ha T
null értékű vagy S
null értékű – tekintsük át T
az S₀
alapul szolgáló típusokat, máskülönben T₀
S₀
egyenlőek T₀
és S
nem azonosak.T
Egy osztály vagy szerkezet csak akkor deklarálhat egy forrástípusból céltípusra S
T
való átalakítást, ha az alábbiak mindegyike igaz:
-
S₀
ésT₀
különböző típusok. -
S₀
VagyT₀
az az osztály vagy struktúratípus, amelyben az operátor deklarációja történik. - Sem
S₀
interface_typeT₀
. - A felhasználó által definiált konverziók kivételével a konvertálás nem létezik a következőre
S
T
vagy onnan:T
S
.
A felhasználó által definiált átalakításokra vonatkozó korlátozásokat a 15.10.4.
10.5.3 Felhasználó által definiált konverziók kiértékelése
A felhasználó által definiált átalakítás egy forráskifejezést konvertál, amelynek forrástípusa lehet egy másik típus, az úgynevezett céltípus. Felhasználó által definiált konverziós központok kiértékelése a forráskifejezés és a céltípus legspecifikusabb , felhasználó által definiált konverziós operátorának megkereséséhez. Ez a meghatározás több lépésből áll:
- Azon osztályok és szerkezetek megkeresése, amelyekből a felhasználó által definiált konverziós operátorok figyelembe lesznek véve. Ez a készlet a forrástípusból és annak alaposztályaiból áll, ha a forrástípus létezik, valamint a céltípusból és annak alaposztályaiból. Ebből a célból feltételezzük, hogy csak osztályok és szerkezetek deklarálhatnak felhasználó által definiált operátorokat, és hogy a nem osztálytípusok nem rendelkeznek alaposztályokkal. Ha a forrás vagy a céltípus null értékű, akkor a rendszer inkább a mögöttes típust használja.
- Ebből a típuskészletből határozza meg, hogy mely felhasználó által meghatározott és emelt konverziós operátorok alkalmazhatók. Ahhoz, hogy az átalakítási operátor alkalmazható legyen, a forráskifejezéstől az operátor operandus típusára szabványos átalakítást (10.4. §) kell végrehajtani, és az operátor eredménytípusáról a céltípusra szabványos átalakítást kell végrehajtani.
- Az alkalmazandó felhasználó által definiált operátorok készletéből állapítsa meg, hogy melyik operátor egyértelműen a legspecifikusabb. Általánosságban elmondható, hogy a legspecifikusabb operátor az az operátor, amelynek operandustípusa "legközelebbi" a forráskifejezéshez, és amelynek eredménytípusa a céltípushoz "legközelebbi". A felhasználó által definiált konverziós operátorokat előnyben részesítik az emelt konverziós operátorok. A legspecifikusabb felhasználó által definiált konverziós operátor létrehozásának pontos szabályait az alábbi alklámokban határozták meg.
A felhasználó által definiált legspecifikusabb konverziós operátor azonosítása után a felhasználó által definiált átalakítás tényleges végrehajtása legfeljebb három lépésből áll:
- Először is, ha szükséges, a forráskifejezéstől a felhasználó által definiált vagy felemelt konverziós operátor operandus típusára történő szabványos átalakítást kell végrehajtania.
- Ezután a felhasználó által definiált vagy felemelt konverziós operátor meghívása a konvertálás végrehajtásához.
- Végül, ha szükséges, a felhasználó által definiált konverziós operátor eredménytípusáról a céltípusra történő szabványos átalakítást hajt végre.
A felhasználó által definiált átalakítások kiértékelése soha nem jár egynél több felhasználó által definiált vagy feloldott konverziós operátorral. Más szóval, a típusról típusra S
T
történő átalakítás soha nem hajtja végre először a felhasználó által definiált átalakítást a típusról S
a másikra X
X
, majd a felhasználó által definiált átalakítástT
.
- A felhasználó által definiált implicit vagy explicit konverziók kiértékelésének pontos definícióit az alábbi alklámokban adtuk meg. A definíciók a következő kifejezéseket használják:
- Ha van egy standard implicit átalakítás (§10.4.2) egy
A
típusból egyB
típusba, és ha semA
, semB
nem interface_type, akkor azt mondjuk, hogyA
átfogottB
, és azt mondjuk, hogyB
átfogjaA
. - Ha létezik egy standard implicit átalakítás (
§10.4.2 ) egykifejezésből egy típusba, és ha sem , sem típusa (ha van) nem interface_típus , akkor azt mondják, hogyfoglalja magában, és azt mondják, hogy magában foglalja. - A típusok halmazában a legfoglalóbb típus az egyetlen típus, amely magában foglalja a készlet összes többi típusát. Ha egyetlen típus sem foglalja magában az összes többi típust, akkor a készletnek nincs legfoglalóbb típusa. Intuitívabb értelemben a legfoglalóbb típus a halmaz "legnagyobb" típusa – az a típus, amelyre a többi típus implicit módon konvertálható.
- A típusok halmazában a legelfoglaltabb típus az a típus, amelyet a készlet összes többi típusa magában foglal. Ha egyetlen típust sem foglal magában az összes többi típus, akkor a készlet nem rendelkezik a legfoglaltabb típussal. Intuitívabb értelemben a legfoglaltabb típus a készlet "legkisebb" típusa – az egyik típus, amely implicit módon konvertálható a többi típusra.
10.5.4 Felhasználó által definiált implicit konverziók
A felhasználó E
által definiált implicit átalakítás kifejezésből típusba T
a következőképpen történik:
Határozza meg a típusokat
S
ésS₀
T₀
a .- Ha
E
van ilyen típus, legyenS
ez a típus. - Ha
S
null értékűek,T
akkor legyenSᵢ
ésTᵢ
legyen a mögöttes típusuk, máskülönben legyenSᵢ
ésTᵢ
S
legyenT
, illetve legyen. - Ha
Sᵢ
típusparaméterekTᵢ
, akkor legyenS₀
ésT₀
legyen a tényleges alaposztályuk, máskülönben legyenS₀
ésT₀
Sₓ
legyenTᵢ
, illetve legyen.
- Ha
Keresse meg azokat a típusokat,
D
amelyek közül a felhasználó által definiált konverziós operátorok lesznek figyelembe véve. Ez a készlet (haS₀
létezik, és egy osztályból vagy struct-ból), a (haS₀
létezik és osztály) alaposztályokbólS₀
ésS₀
(haT₀
osztályból vagy szerkezetből) állT₀
. A rendszer csak akkor ad hozzá típust a készlethezD
, ha nem létezik identitásátalakítás egy másik típusra, amely már szerepel a készletben.Keresse meg a felhasználó által definiált és feloldott konverziós operátorok készletét.
U
Ez a készlet a felhasználó által definiált és emelt implicit konverziós operátorokból áll, amelyeket az osztályok vagy a szerkezetek deklaráltakD
abban, hogy az átalakítás egy olyan típusból, amely magában foglaljaE
T
a . HaU
üres, a konvertálás nincs meghatározva, és fordítási időhiba lép fel.- Ha
S
létezik, és a konvertáltU
S
operátorok bármelyike az , akkorSₓ
az leszS
. -
Sₓ
Ellenkező esetben a legfoglaltabb típus az operátorok forrástípusainak kombinált készletében a következőbenU
: . Ha pontosan egy legfoglaltabb típus nem található, akkor az átalakítás nem egyértelmű, és fordítási időhiba lép fel.
- Ha
Keresse meg az operátorok legspecifikusabb céltípusát
Tₓ
a következő helyenU
:- Ha a konvertált
U
T
operátorok bármelyike , akkorTₓ
az .T
-
Tₓ
Ellenkező esetben az operátorokU
céltípusainak kombinált készletében a legfoglalóbb típus a . Ha pontosan egy legfoglalóbb típus nem található, akkor az átalakítás nem egyértelmű, és fordítási időhiba lép fel.
- Ha a konvertált
Keresse meg a leginkább specifikus konverziós operátort:
- Ha
U
pontosan egy felhasználó által definiált konverziós operátort tartalmaz, amelyrőlSₓ
Tₓ
áttér, akkor ez a leginkább specifikus konverziós operátor. - Ellenkező esetben, ha
U
pontosan egy emelt konverziós operátort tartalmaz, amely áttérSₓ
a konvertálásraTₓ
, akkor ez a leginkább specifikus konverziós operátor. - Ellenkező esetben az átalakítás nem egyértelmű, és fordítási időhiba lép fel.
- Ha
Végül alkalmazza az átalakítást:
- Ha az E még nem rendelkezik ilyen típussal
Sₓ
, akkor a rendszer szabványos implicit átalakítástE
Sₓ
hajt végre. - A legspecifikusabb konverziós operátort hívjuk meg a konvertáláshoz
Sₓ
Tₓ
. - Ha
Tₓ
nemT
, akkor egy standard implicit átalakításTₓ
T
lesz végrehajtva.
- Ha az E még nem rendelkezik ilyen típussal
A felhasználó által definiált implicit átalakítás típusról típusra S
T
akkor áll fenn, ha egy felhasználó által definiált implicit átalakítás létezik egy típusváltozóról S
a típusra T
.
10.5.5 Felhasználó által definiált explicit konverziók
A felhasználó által definiált explicit konverzió egy kifejezésből E
típusra T
az alábbiak szerint történik:
- Határozza meg a típusokat
S
ésS₀
T₀
a .- Ha
E
van ilyen típus, legyenS
ez a típus. - Ha
S
null értékűek,T
akkor legyenSᵢ
ésTᵢ
legyen a mögöttes típusuk, máskülönben legyenSᵢ
ésTᵢ
S
legyenT
, illetve legyen. - Ha
Sᵢ
típusparaméterekTᵢ
, akkor legyenS₀
ésT₀
legyen a tényleges alaposztályuk, máskülönben legyenS₀
ésT₀
Sᵢ
legyenTᵢ
, illetve legyen.
- Ha
- Keresse meg azokat a típusokat,
D
amelyek közül a felhasználó által definiált konverziós operátorok lesznek figyelembe véve. Ez a készlet (haS₀
létezik, és egy osztály vagy struct), az alaposztályokS₀
(haS₀
léteznek és osztály),S₀
(haT₀
osztály vagy szerkezet) és a (haT₀
osztály) alaposztályaiT₀
.T₀
A rendszer csak akkor ad hozzá típust a készlethezD
, ha nem létezik identitásátalakítás egy másik típusra, amely már szerepel a készletben. - Keresse meg a felhasználó által definiált és feloldott konverziós operátorok készletét.
U
Ez a halmaz a felhasználó által definiált és az osztályok által deklarált implicit vagy explicit konverziós operátorokból áll, amelyekbenD
az osztályokat magában foglalóE
vagy magában foglalóS
típusból (ha létezik) áttér egy olyan típusra, amely magában foglalja vagy magában foglaljaT
azt. HaU
üres, a konvertálás nincs meghatározva, és fordítási időhiba lép fel. - Keresse meg az operátorok legspecifikusabb forrástípusát
Sₓ
a következő helyenU
:- Ha az S létezik, és a konvertált
U
S
operátorok bármelyike, akkorSₓ
az .S
- Ellenkező esetben, ha a konvertált operátorok bármelyike olyan típusokból konvertálódik, amelyek magukban
U
foglaljákE
azokat, akkorSₓ
az adott operátorok forrástípusainak együttes készletében a legelfoglaltabb típus. Ha nem található a legfoglaltabb típus, akkor az átalakítás nem egyértelmű, és fordítási időhiba lép fel. -
Sₓ
Ellenkező esetben a legfoglalóbb típus az operátorok kombinált forrástípus-készletébenU
. Ha pontosan egy legfoglalóbb típus nem található, akkor az átalakítás nem egyértelmű, és fordítási időhiba lép fel.
- Ha az S létezik, és a konvertált
- Keresse meg az operátorok legspecifikusabb céltípusát
Tₓ
a következő helyenU
:- Ha a konvertált
U
T
operátorok bármelyike , akkorTₓ
az .T
- Ellenkező esetben, ha a konvertált operátorok
U
bármelyike olyan típussá alakul át, amelyT
magában foglalja azokat, akkorTₓ
az adott operátorok céltípusainak kombinált készletében a legfoglalóbb típus. Ha pontosan egy legfoglalóbb típus nem található, akkor az átalakítás nem egyértelmű, és fordítási időhiba lép fel. -
Tₓ
Ellenkező esetben az operátorokU
céltípusainak kombinált készletében a legelfoglaltabb típus a . Ha nem található a legfoglaltabb típus, akkor az átalakítás nem egyértelmű, és fordítási időhiba lép fel.
- Ha a konvertált
- Keresse meg a leginkább specifikus konverziós operátort:
- Ha az U pontosan egy felhasználó által definiált konverziós operátort tartalmaz, amelyről
Sₓ
Tₓ
áttér, akkor ez a leginkább specifikus konverziós operátor. - Ellenkező esetben, ha
U
pontosan egy emelt konverziós operátort tartalmaz, amely áttérSₓ
a konvertálásraTₓ
, akkor ez a leginkább specifikus konverziós operátor. - Ellenkező esetben az átalakítás nem egyértelmű, és fordítási időhiba lép fel.
- Ha az U pontosan egy felhasználó által definiált konverziós operátort tartalmaz, amelyről
- Végül alkalmazza az átalakítást:
- Ha
E
még nem rendelkezik ilyen típussal, akkor az ESₓ
típusbólSₓ
szabványos explicit átalakítást hajt végre. - A rendszer meghívja a legspecifikusabb, felhasználó által definiált konverziós operátort a konvertáláshoz
Sₓ
Tₓ
. - Ha
Tₓ
nemT
, akkor a szokásos explicit átalakításTₓ
T
lesz végrehajtva.
- Ha
A felhasználó által definiált explicit átalakítás típusról típusra S
T
akkor áll fenn, ha egy felhasználó által definiált explicit átalakítás létezik egy típusváltozóról S
a típusra T
.
10.6 Null értékű típusok konvertálása
10.6.1 Null értékű konverziók
A null értékű konverziók lehetővé teszik, hogy a nem null értékű értéktípusokon működő előre definiált konverziók az ilyen típusok null értékű formáival is használhatók legyenek. Az előre definiált implicit vagy explicit konverziók esetében, amelyek nem null értékű értéktípusból S
nem null értékű típussá T
alakulnak át (10.2.2. §, 10.2.3. §, 10.2.4. §, 10.2.11. §, 10.3.2. és 10.3.3. §), a következő null értékű konverziók léteznek:
- Implicit vagy explicit konverzió a
S?
T?
- Implicit vagy explicit konverzió a
S
T?
- Explicit átalakítás a célról a .-ra
S?
T
.
A null értékű átalakítás önmagában implicit vagy explicit konverzióként van besorolva.
Egyes null értékű konverziók standard konverziókként vannak besorolva, és egy felhasználó által meghatározott átalakítás részeként is előfordulhatnak. Pontosabban az összes implicit null értékű konverzió standard implicit konverzióként van besorolva (10.4.2. §), és a 10.4.3 .
Null értékű átalakítás kiértékelése az alapul szolgáló átalakítás S
alapján a T
következő módon:
- Ha a null értékű átalakítás a következőről
S?
T?
:- Ha a forrás értéke null (
HasValue
a tulajdonság értékefalse
), akkor az eredmény a típusT?
null értéke. - Ellenkező esetben a rendszer az átalakítást a következőre történő leállításként
S?
S
értékeli ki, majd az alapul szolgáló átalakítástS
T
a következőre, majd a sortöréstT
a következőreT?
.
- Ha a forrás értéke null (
- Ha a null értékű átalakítás a következőre
S
T?
történik, a rendszer az átalakítást a mögöttes átalakításkéntS
T
értékeli ki, amelyet egy sortörésT
T?
követ. - Ha a null értékű átalakításról a következőre
S?
van állítva, a rendszer a konvertálást át nem vonókéntT
S?
értékeli ki, majd az alapul szolgáló átalakításból aS
következőreS
.T
10.6.2 Emelt konverziók
Mivel a felhasználó által definiált átalakítási operátor nem null értékű értéktípusból S
nem null értékűre T
konvertál, létezik egy feloldott konverziós operátor, amely a S?
T?
következőre konvertál. Ez az emelt konverziós operátor a felhasználó által definiált átalakítás S?
S
és S
T
a hozzá való körbefuttatás T
T?
közötti váltást hajtja végre, azzal a kivételével, hogy a null értékű S?
érték közvetlenül null értékűvé T?
alakul. A feloldott konverziós operátorok implicit vagy explicit besorolása megegyezik a mögöttes, felhasználó által definiált konverziós operátorral.
10.7 Névtelen függvénykonverziók
10.7.1 Általános
A anonymous_method_expression vagy lambda_expression névtelen függvényként van besorolva (12.19. §). A kifejezés nem rendelkezik típussal, de implicit módon konvertálható kompatibilis delegált típussá. Egyes lambda-kifejezések implicit módon konvertálhatók kompatibilis kifejezésfatípussá.
A névtelen függvények F
kompatibilisek a megadott delegált típussal D
:
- Ha
F
anonymous_function_signature tartalmaz, akkorD
F
ugyanazzal a paraméterszámmal kell rendelkeznie. - Ha
F
nem tartalmaz anonymous_function_signature, akkorD
nulla vagy több bármilyen típusú paraméter lehet, feltéve, hogy a kimeneti paraméter egyik paramétereD
sem. - Ha
F
explicit módon beírt paraméterlistával rendelkezik, minden paraméterbenD
ugyanazok a módosítók szerepelnek, mint a megfelelő paraméterbenF
, és a megfelelő paraméterF
között identitáskonvertálás áll fenn. - Ha
F
implicit módon beírt paraméterlistával rendelkezik,D
nincs hivatkozási vagy kimeneti paramétere. - Ha a törzs
F
egy kifejezés , ésD
vagy üres visszatérési típussal rendelkezik , vagyF
aszinkron, ésD
visszatérési típussal rendelkezik«TaskType»
(15.14.1. §), akkor amikor az egyes paraméterekF
a megfelelő paraméterD
típusát adják meg, akkor a törzseF
egy érvényes kifejezés (w.r.t §12), amely statement_expression lenne engedélyezve (13.7. §). - Ha a törzs
F
egy blokk, ésD
vagy üres visszatérési típussal aszinkron, ésF
visszatérési típussal rendelkezikD
, akkor amikor az egyes paraméterek«TaskType»
a megfelelő paraméterF
típusát adják meg, a törzsD
egy érvényes blokk (w.r.tF
), amelyben egyetlen utasítás sem határoz meg kifejezést. - Ha a törzs
F
egy kifejezés, és akárF
nem aszinkron ésD
nem rendelkezikvoid
visszatérésiT
típussal, vagyF
aszinkron ésD
rendelkezik«TaskType»<T>
visszatérési típussal (15.14.1. §), akkor haF
minden egyes paramétere a megfelelőD
paraméter típusát kapja meg, a törzsF
olyan érvényes kifejezés (lásd §12), amely implicit módon átalakíthatóT
-re. - Ha a törzs
F
egy blokk, és vagyF
nem aszinkron, ésD
nem érvénytelen visszatérési típussalT
rendelkezik, vagyF
aszinkron, ésD
visszatérési típussal rendelkezik«TaskType»<T>
, akkor amikor az egyes paraméterekF
a megfelelő paraméterD
típusát adják meg, akkor a törzsF
egy érvényes utasításblokk (w.r.t §13.3) egy nem elérhető végponttal, amelyben minden visszatérési utasítás implicit módon átalakíthatóT
kifejezést ad meg.
Példa: Az alábbi példák a következő szabályokat szemléltetik:
delegate void D(int x); D d1 = delegate { }; // Ok D d2 = delegate() { }; // Error, signature mismatch D d3 = delegate(long x) { }; // Error, signature mismatch D d4 = delegate(int x) { }; // Ok D d5 = delegate(int x) { return; }; // Ok D d6 = delegate(int x) { return x; }; // Error, return type mismatch delegate void E(out int x); E e1 = delegate { }; // Error, E has an output parameter E e2 = delegate(out int x) { x = 1; }; // Ok E e3 = delegate(ref int x) { x = 1; }; // Error, signature mismatch delegate int P(params int[] a); P p1 = delegate { }; // Error, end of block reachable P p2 = delegate { return; }; // Error, return type mismatch P p3 = delegate { return 1; }; // Ok P p4 = delegate { return "Hello"; }; // Error, return type mismatch P p5 = delegate(int[] a) // Ok { return a[0]; }; P p6 = delegate(params int[] a) // Error, params modifier { return a[0]; }; P p7 = delegate(int[] a) // Error, return type mismatch { if (a.Length > 0) return a[0]; return "Hello"; }; delegate object Q(params int[] a); Q q1 = delegate(int[] a) // Ok { if (a.Length > 0) return a[0]; return "Hello"; };
záró példa
Példa: Az alábbi példák egy általános delegálttípust
Func<A,R>
használnak, amely egy olyan függvényt jelöl, amely egy típusA
argumentumát veszi fel, és egy típusértéketR
ad vissza:delegate R Func<A,R>(A arg);
A hozzárendelésekben
Func<int,int> f1 = x => x + 1; // Ok Func<int,double> f2 = x => x + 1; // Ok Func<double,int> f3 = x => x + 1; // Error Func<int, Task<int>> f4 = async x => x + 1; // Ok
az egyes névtelen függvények paraméter- és visszatérési típusai annak a változónak a típusából vannak meghatározva, amelyhez a névtelen függvény hozzá van rendelve.
Az első hozzárendelés sikeresen konvertálja a névtelen függvényt a delegált típussá
Func<int,int>
, mert adott típusx
int
eseténx + 1
egy érvényes kifejezés, amely implicit módon átalakítható típussáint
.Hasonlóképpen, a második hozzárendelés sikeresen konvertálja a névtelen függvényt a Func<int delegált típusúra, dupla> értékre, mert a (típus
x + 1
) eredményeint
implicit módon átalakítható típussádouble
.A harmadik hozzárendelés azonban fordítási időhiba, mert adott típus esetén
x
a (típusdouble
) eredményex + 1
nem implicit módon konvertálható típussádouble
.int
A negyedik hozzárendelés sikeresen konvertálja a névtelen aszinkron függvényt delegált típussá
Func<int, Task<int>>
, mert a (típus)x + 1
eredményeint
implicit módon konvertálható az aszinkron lambda tényleges visszatérési típusáraint
, amelynek visszatérési típusaTask<int>
van.záró példa
A lambda kifejezés F
kompatibilis a kifejezésfa típusával Expression<D>
, ha F
kompatibilis a delegált típussal D
. Ez nem vonatkozik a névtelen metódusokra, csak a lambda kifejezésekre.
A névtelen függvények befolyásolhatják a túlterhelés feloldását, és részt vehetnek a típuskövetkeztetésben. További részletekért lásd a 12.6 .
10.7.2 Névtelen függvények delegált típusokké alakításának kiértékelése
A névtelen függvények delegált típusúvá alakítása egy delegált példányt hoz létre, amely a névtelen függvényre és a rögzített külső változók (esetleg üres) készletére hivatkozik, amelyek a kiértékelés időpontjában aktívak. A meghatalmazott meghívása után a rendszer végrehajtja a névtelen függvény törzsét. A rendszer a törzsben lévő kódot a meghatalmazott által hivatkozott rögzített külső változók készletével hajtja végre. A delegate_creation_expression (12.8.17.5. §) alternatív szintaxisként használható névtelen metódus delegált típussá alakításához.
A névtelen függvényből előállított delegált meghívási listája egyetlen bejegyzést tartalmaz. A delegált pontos célobjektuma és célmetódusa nincs meghatározva. Konkrétan nem határozza meg, hogy a delegált null
célobjektuma, a this
belefoglaló függvény tagjának értéke vagy más objektum.
Az azonos (esetleg üres) rögzített külső változópéldányokkal azonos delegált típusú névtelen függvények konvertálása ugyanahhoz a delegálttípushoz engedélyezett (de nem kötelező), hogy ugyanazt a delegált példányt adja vissza. A szemantikailag azonos kifejezés azt jelenti, hogy a névtelen függvények végrehajtása minden esetben ugyanazokat a hatásokat fogja eredményezni ugyanazokkal az argumentumokkal. Ez a szabály lehetővé teszi az alábbi kódhoz hasonló kód optimalizálását.
delegate double Function(double x);
class Test
{
static double[] Apply(double[] a, Function f)
{
double[] result = new double[a.Length];
for (int i = 0; i < a.Length; i++)
{
result[i] = f(a[i]);
}
return result;
}
static void F(double[] a, double[] b)
{
a = Apply(a, (double x) => Math.Sin(x));
b = Apply(b, (double y) => Math.Sin(y));
...
}
}
Mivel a két névtelen függvény-delegált azonos (üres) rögzített külső változókészlettel rendelkezik, és mivel a névtelen függvények szemantikailag azonosak, a fordítók számára engedélyezett, hogy a meghatalmazottak ugyanarra a célmódszerre hivatkozjanak. Valójában a fordító mindkét névtelen függvénykifejezésből ugyanazt a delegált példányt adhatja vissza.
10.7.3 A lambda kifejezés fatípusokra való konvertálásának kiértékelése
A lambda kifejezés kifejezésfa típusúvá alakítása kifejezésfát hoz létre (8.6. §). Pontosabban a lambda kifejezés konvertálásának kiértékelése olyan objektumstruktúrát hoz létre, amely magában a lambda kifejezés szerkezetét jelöli.
Nem minden lambda kifejezés konvertálható kifejezésfa típusúvá. A kompatibilis delegált típusra való konvertálás mindig létezik, de a megvalósítás által meghatározott okok miatt fordítási időpontban meghiúsulhat.
Megjegyzés: A lambda kifejezés kifejezésfatípussá való konvertálásának gyakori okai a következők:
- Blokktörzse van
- Rendelkezik a
async
módosítóval- Hozzárendelés-operátort tartalmaz
- Kimeneti vagy referenciaparamétert tartalmaz
- Dinamikusan kötött kifejezést tartalmaz
végjegyzet
10.8 Metóduscsoport-átalakítások
Implicit átalakítás létezik egy metóduscsoportból (12.2. §) egy kompatibilis meghatalmazotti típusra (20.4. §). Ha D
egy delegált típus, és E
egy metóduscsoportként besorolt kifejezés, akkor D
akkor kompatibilis E
a ha és csak akkor, ha E
legalább egy metódust tartalmaz, amely a normál formájában alkalmazható (12.6.4.2. §) bármely argumentumlistára (12.6.2.§), amely a paramétertípusoknak és módosítóknak D
megfelelő típusokat és módosítókat tartalmazza az alábbiakban leírtak szerint.
A metóduscsoportból E
delegált típusra D
történő konvertálás fordítási idő alkalmazását az alábbiakban ismertetjük.
- Egyetlen metódus
M
van kiválasztva az űrlap egy metódushívásának (E(A)
. §) megfelelően, a következő módosításokkal:- Az argumentumlista
A
a kifejezéseket tartalmazó lista, amely változóként van besorolva,in
és a megfelelő paraméter típusával és módosítójával (out
vagyref
) a parameter_listD
, kivéve a típusparamétereketdynamic
, ahol a megfelelő kifejezés típusaobject
helyettdynamic
a típus szerepel. - A vizsgált módszerek csak azok a módszerek, amelyek normál formájukban alkalmazhatók, és nem hagynak ki választható paramétereket (12.6.4.2. §). Így a jelölt metódusok figyelmen kívül lesznek hagyva, ha csak a kibontott formájukban alkalmazhatók, vagy ha egy vagy több választható paraméterük nem rendelkezik megfelelő paraméterrel.
D
- Az argumentumlista
- Az átalakítás akkor tekinthető létezőnek, ha a §12.8.10.2 algoritmusa §).
- Ha a kijelölt metódus
M
egy példánymetódus, a meghatalmazott célobjektumát a társított példánykifejezésE
határozza meg. - Ha a kijelölt metódus
M
egy bővítménymetódus, amelyet egy példánykifejezés taghozzáférése jelöl, az a példánykifejezés határozza meg a meghatalmazott célobjektumát. - Az átalakítás eredménye egy típusérték
D
, nevezetesen egy delegált, amely a kiválasztott metódusra és a célobjektumra hivatkozik.
Példa: Az alábbiak a metóduscsoport-átalakításokat szemléltetik:
delegate string D1(object o); delegate object D2(string s); delegate object D3(); delegate string D4(object o, params object[] a); delegate string D5(int i); class Test { static string F(object o) {...} static void G() { D1 d1 = F; // Ok D2 d2 = F; // Ok D3 d3 = F; // Error – not applicable D4 d4 = F; // Error – not applicable in normal form D5 d5 = F; // Error – applicable but not compatible } }
A metóduscsoportot
d1
implicit módon átalakító hozzárendelésF
típusértékkéD1
.A hozzárendelés
d2
bemutatja, hogyan hozható létre delegált egy kevésbé származtatott (contravariant) paramétertípussal és származtatottabb (kovariant) visszatérési típussal rendelkező metódushoz.A hozzárendelés azt
d3
mutatja be, hogy nem létezik átalakítás, ha a metódus nem alkalmazható.Az a hozzárendelés, amely
d4
bemutatja, hogy a metódusnak a szokásos formájában kell alkalmazhatónak lennie.Az a hozzárendelés, amely bemutatja,
d5
hogy a delegált és a metódus paraméter- és visszatérési típusai csak referenciatípusok esetén térhetnek el egymástól.záró példa
Az összes többi implicit és explicit konverzióhoz hasonlóan az öntött operátor is használható egy adott átalakítás explicit végrehajtására.
Példa: Így a példa
object obj = new EventHandler(myDialog.OkClick);
ehelyett megírható
object obj = (EventHandler)myDialog.OkClick;
záró példa
A metóduscsoportok konvertálása általános metódusra hivatkozhat, akár a típusargumentumok E
explicit megadásával, akár típuskövetkeztetéssel (12.6.3. §). Típuskövetkeztetés használata esetén a delegált paramétertípusai argumentumtípusokként lesznek használva a következtetési folyamat során. A delegált visszatérési típusa nem használható a következtetéshez. Függetlenül attól, hogy a típusargumentumok meg vannak-e adva vagy kikövetkeztetettek, a metóduscsoport-átalakítási folyamat részét képezik; ezek a típusargumentumok a célmetódus meghívásához az eredményként kapott meghatalmazott meghívásakor.
Példa:
delegate int D(string s, int i); delegate int E(); class X { public static T F<T>(string s, T t) {...} public static T G<T>() {...} static void Main() { D d1 = F<int>; // Ok, type argument given explicitly D d2 = F; // Ok, int inferred as type argument E e1 = G<int>; // Ok, type argument given explicitly E e2 = G; // Error, cannot infer from return type } }
záró példa
A metóduscsoportok befolyásolhatják a túlterhelés feloldását, és részt vehetnek a típuskövetkeztetésben. További részletekért lásd a 12.6 .
A metóduscsoport-átalakítás futásidejű kiértékelése az alábbiak szerint történik:
- Ha a fordítási időpontban kiválasztott metódus egy példánymetódus, vagy egy olyan bővítménymetódus, amely példánymetódusként érhető el, a delegált célobjektuma a következőhöz
E
társított példánykifejezésből lesz meghatározva:- A példánykifejezés kiértékelése történik. Ha ez a kiértékelés kivételt okoz, a rendszer nem hajt végre további lépéseket.
- Ha a példánykifejezés egy reference_type, a példánykifejezés által kiszámított érték lesz a célobjektum. Ha a kijelölt metódus egy példánymetódus, és a célobjektum az
null
, akkor a rendszer egySystem.NullReferenceException
műveletet hajt végre, és nem hajtja végre a további lépéseket. - Ha a példánykifejezés egy value_type, a rendszer egy boxing műveletet (§10.2.9) hajt végre az érték objektummá alakításához, és ez az objektum lesz a célobjektum.
- Ellenkező esetben a kijelölt metódus egy statikus metódushívás része, a delegált célobjektuma pedig a
null
. - A delegált típusú
D
delegáltpéldány a fordítási időpontban meghatározott metódusra és a fent kiszámított célobjektumra mutató hivatkozással érhető el, az alábbiak szerint:- Az átalakítás engedélyezett (de nem kötelező) egy meglévő delegált példány használatára, amely már tartalmazza ezeket a hivatkozásokat.
- Ha egy meglévő példány nem lett újra felhasználva, létrejön egy új példány (20.5.§). Ha nem áll rendelkezésre elegendő memória az új példány lefoglalásához, a rendszer eldobja
System.OutOfMemoryException
a példányt. Ellenkező esetben a példány inicializálása a megadott hivatkozásokkal történik.
ECMA C# draft specification