Megosztás a következőn keresztül:


10 Átalakítások

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 intlong való átalakítás implicit, így a típuskifejezések int implicit módon kezelhetők típusként long. Az ellenkező átalakítás típusról típusra longintexplicit, 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 és T, minden típushoz T.
  • Bármely referenciatípus között T és T? azok esetében T.
  • Között object és dynamic.
  • 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 t1t2t3 típusainak két eleme van: egy int és egy string. A tuple elemtípusok maguk is lehetnek a rekordok, például a t4, t5és t6a . 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 tuplesek t4t5típusai és t6a .

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, longfloat, doublevagy decimal.
  • Feladóbyte, short, ushortint, uint, long, ulong, float, , doublevagy decimal.
  • Feladóshort, int, long, floatdouble, vagy decimal.
  • Feladóushort, int, uintlong, ulong, float, doublevagy decimal.
  • From int , long, , floator double.decimal
  • Feladóuint, long, ulong, floatdouble, vagy decimal.
  • longFrom float , , doubleor decimal.
  • ulongFrom float , , doubleor decimal.
  • Feladóchar, ushort, intuint, long, ulong, float, double, vagy decimal.
  • float-tól double-ig.

intAz , , uint, long vagy ulongfloat a forrásból vagy long a forrásból ulongdouble 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 objectdynamic.
  • S származik.T
  • Bármely bármely S, a megadott T implementálások S.
  • S származik.T
  • egy elemtípussal SSᵢT, feltéve, hogy az alábbiak mindegyike igaz:
    • S és T csak elemtípusban különbözik. Más szóval, S és T ugyanannyi dimenzióval rendelkezik.
    • Implicit referenciakonvertálás létezik a helyről Sᵢ a másikra Tᵢ.
  • 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ől S a másikra T.
  • A array_typeSystem.Array és az általa implementálandó felületektől kezdve.
  • A delegate_typeSystem.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_typeT, ha implicit identitással vagy hivatkozási átalakítással rendelkezik egy , és T₀ identitásátalakítással T₀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ípusra T₀ , és T₀ variancia-átalakítható (18.2.3.3.3. §)-ról T.
  • 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 (HasValuehamis), 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ész Iimplementálását, amelynek neve boxosztály S_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ének S megadása mostantól a kifejezés new 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ások

S 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ípusa Svan, a futtatókörnyezet típusának ellenőrzése is 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 pbox során következik be, a p másolást okozza. Ha Point ehelyett deklarálták class volna, a 20 érték kimenet lenne, mert pbox 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 Tfutá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ó objecta 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 s2i 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ű stringtípusától a céltípusig. A konvertálás a következőre történik, string de nem a következőre int: .

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á sbytealakítható, byteshortushortuintfeltéve, ulonghogy a constant_expression értéke a céltípus tartományán belül van.
  • Egy constant_expressionlong típussá ulongalakí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 TCa bármely alaposztályigTC, valamint TCa .
  • A T interface_type I
  • A T megadott U típusparamétertől T függ U (15.2.5. §).

    Megjegyzés: Mivel T ismert, hogy referenciatípus, a hatókörön Tbelül a futtatási idő típusa U mindig referenciatípus lesz, még akkor is, ha U 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 TCa bármely alaposztályigTC, valamint TCa .

    Megjegyzés: C az egyik típusSystem.ObjectSystem.ValueType, vagy System.Enum (más néven T referenciatípus) lesz. végjegyzet

  • A T interface_type I

Olyan type_parameterT esetében, amelyről ismert, hogy nem referenciatípus, implicit átalakítás történik a megadott TU típusparaméterre TU. 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 TS , ha implicit átalakítással rendelkezik egy referenciatípusra S₀ , és S₀ identitásátalakítással Srendelkezik. Futtatáskor a konvertálás ugyanúgy történik, mint a S₀konvertálás.
  • Kapcsolódási típusról illesztőtípusraT, ha implicit átalakítással rendelkezik egy illesztőtípusra II₀, és I₀ variancia-átalakítható (I. §). Futásidőben, ha T é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 Ekié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és t2t4 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őrenullint: . 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, uintulong, vagy char.
  • Feladó byte vagy sbytechar.
  • Feladóshort, sbyte, byte, ushortuint, ulongvagy char.
  • From ushort , sbyte, , byteor short.char
  • Feladóint, sbyte, byteshort, ushort, uint, ulongvagy char.
  • Feladóuint, sbyte, byte, shortushort, intvagy char.
  • Feladólong, sbyte, byteshort, ushort, int, uint, ulong, vagy char.
  • Feladóulong, sbyte, byteshort, ushort, int, uint, long, vagy char.
  • charFrom sbyte , , byteor short.
  • Feladófloat, sbyte, byte, shortushort, int, uint, long, ulongcharvagy decimal.
  • Feladódouble, sbyte, byte, shortushort, int, uint, long, ulong, char, float, vagy decimal.
  • Feladódecimal, sbyte, byte, shortushort, int, uint, long, ulong, char, float, vagy double.

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 a System.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 egy System.OverflowException értéket ad.
  • Az integrált típusból float vagy double 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.
    • 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.
  • double floatA konvertálás során az érték a double legközelebbi float értékre lesz kerekítve. Ha az double érték túl kicsi ahhoz, hogy az értékként floatlegyen jelölve, az eredmény nullává válik ugyanazzal a jellel, mint az érték. Ha az érték nagysága double túl nagy ahhoz, hogy az értékként floatlegyen jelölve, az eredmény végtelenné válik ugyanazzal a jellel, mint az érték. Ha az double érték NaN, az eredmény szintén NaN.
  • A forrásértéket float ábrázolássá double alakítjuk át, decimaldecimalé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 decimallegyen jelölve, az eredmény nullává válik, megőrizve az eredeti érték előjelét, ha decimal támogatja az aláírt nulla értékeket.
    • Ha a forrásérték mérete túl nagy ahhoz, hogy végtelenként decimallegyen 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.
  • A másikról a másikra decimal való átalakítás float esetén az double érték a legközelebbire decimal vagy double é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ány float és double, de ez nem garantált. Végtelen vagy NaN-értékek nélküli ábrázolások esetén decimal , és a tartomány kisebb, mint floata végtelen vagy a NaN közötti átalakítás decimalfloat eredménye, vagy double 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, intuintlongulongcharfloat, double, vagy decimal bármely enum_type.
  • Bármely sbytebyteshortushort, , intuint, 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ő EintE-ról byte-ra történő konvertálás explicit numerikus átalakításként történik (§10.3.2) int-ről byte- és byte-ről E-ra történő átalakítás implicit numerikus átalakításként (§10.2.3) történik byte-ról int- 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_typeS, a megadott T alaposztály.S
  • Bármely class_typeS , feltéve T , hogy nem lezárt, és feltéveS, hogy nem implementálódik .S
  • Bármely interface_typeS , feltéve T , hogy nem lezárt vagy biztosított T eszközök .T
  • A megadott interface_typeST nem származik .S
  • egy elemtípussal SSᵢT, feltéve, hogy az alábbiak mindegyike igaz:
    • S és T csak elemtípusban különbözik. Más szóval, S és T ugyanannyi dimenzióval rendelkezik.
    • Explicit referenciakonvertálás létezik a helyről Sᵢ a .-ra Tᵢ.
  • 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 type T[], feltéve, hogy van egy identitásátalakítás vagy explicit hivatkozás konvertálása A-ról S 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ípusraS, és T az identitás áttér a referenciatípusra ST₀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ípusra ST₀, és T₀ variancia-átalakítható TT 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 azonos D<T₁...Tᵥ>a következő típusparaméterekkel XᵢD:
    • Ha Xᵢ invariáns, akkor Sᵢ megegyezik a Tᵢ.
    • 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, akkor Sᵢ azonos Tᵢ vagy mindkét referenciatípus.
  • 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 Ekié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_value I₀ és az identitás konvertálása I a következőre I₀történik:
  • Az interface_typeI 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 vagy I₀ variancia szempontjából konvertálható I-re, vagy I 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 nullaz, 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_typeS való nem dobozos konvertálása a kifejezés ((S_Boxing)box).valuevégrehajtásából áll. Így az állítások

object 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 CT.TCT
  • Bármely interface_type.T
  • Minden T interface_type
  • , U amelytől T függ T (U. §).

    Megjegyzés: Mivel T ismert, hogy referenciatípus, a hatókörön Tbelül a futtatási idő típusa mindig referenciatípus lesz, még akkor is, ha U 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 CT.TCT

    Megjegyzés: A C az egyik típus System.Object, System.ValueTypevagy System.Enum (más néven T 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.§), Tobject amelyet egy explicit hivatkozási átalakítás objectIkövet. Futtatáskor, ha T é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, ha T referenciatípusról van szó, a konvertálás explicit referenciakonvertálásként lesz végrehajtva.
  • A megadott U típusparamétertől TT függ U (15.2.5. §). Futtatáskor, ha T értéktípus, és U 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 é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 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 tlong engedélyezve lett volna, könnyen előfordulhat, hogy ez X<int>.F(7) vissza fog térni 7L. 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 dobozos int 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 AB létezik, akkor a standard explicit átalakítás típusról típusra AB és típusról típusra BAlé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 Seseté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 ST való átalakítást, ha az alábbiak mindegyike igaz:

  • S₀ és T₀ különböző típusok.
  • S₀ Vagy T₀ 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 ST vagy onnan: TS.

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 ST 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 XX, 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 egy Btípusba, és ha sem A, sem B nem interface_type, akkor azt mondjuk, hogy AátfogottB, és azt mondjuk, hogy BátfogjaA.
  • Ha létezik egy standard implicit átalakítás (§10.4.2) egy kifejezésből egy típusba, és ha sem , sem típusa (ha van) nem interface_típus, akkor azt mondják, hogy foglalja magában, és azt mondják, hogymagá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és S₀T₀a .

    • Ha E van ilyen típus, legyen S ez a típus.
    • Ha S null értékűek, T akkor legyen Sᵢ és Tᵢ legyen a mögöttes típusuk, máskülönben legyen Sᵢ és TᵢSlegyenT, illetve legyen.
    • Ha Sᵢ típusparaméterekTᵢ, akkor legyen S₀ és T₀ legyen a tényleges alaposztályuk, máskülönben legyen S₀ és T₀Sₓ legyenTᵢ, illetve legyen.
  • Keresse meg azokat a típusokat, Damelyek közül a felhasználó által definiált konverziós operátorok lesznek figyelembe véve. Ez a készlet (ha S₀ létezik, és egy osztályból vagy struct-ból), a (ha S₀ létezik és osztály) alaposztályokból S₀ és S₀ (ha T₀ osztályból vagy szerkezetből) áll T₀ . A rendszer csak akkor ad hozzá típust a készlethez D , 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áltak D abban, hogy az átalakítás egy olyan típusból, amely magában foglalja ETa . Ha U üres, a konvertálás nincs meghatározva, és fordítási időhiba lép fel.

    • Ha S létezik, és a konvertált USoperátorok bármelyike az , akkor Sₓ az lesz S.
    • 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.
  • Keresse meg az operátorok legspecifikusabb céltípusát Tₓa következő helyen U:

    • Ha a konvertált UToperátorok bármelyike , akkor Tₓ az .T
    • Tₓ Ellenkező esetben az operátorok Ucé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.
  • 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ő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ér Sₓ a konvertálásra Tₓ, 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.
  • 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ást ESₓ hajt végre.
    • A legspecifikusabb konverziós operátort hívjuk meg a konvertáláshoz SₓTₓ.
    • Ha Tₓ nem T, akkor egy standard implicit átalakítás TₓT lesz végrehajtva.

A felhasználó által definiált implicit átalakítás típusról típusra ST 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és S₀T₀a .
    • Ha E van ilyen típus, legyen S ez a típus.
    • Ha S null értékűek, T akkor legyen Sᵢ és Tᵢ legyen a mögöttes típusuk, máskülönben legyen Sᵢ és TᵢSlegyenT, illetve legyen.
    • Ha Sᵢ típusparaméterekTᵢ, akkor legyen S₀ és T₀ legyen a tényleges alaposztályuk, máskülönben legyen S₀ és T₀Sᵢ legyenTᵢ, illetve legyen.
  • Keresse meg azokat a típusokat, Damelyek közül a felhasználó által definiált konverziós operátorok lesznek figyelembe véve. Ez a készlet (ha S₀ létezik, és egy osztály vagy struct), az alaposztályok S₀ (ha S₀ léteznek és osztály), S₀ (ha T₀ osztály vagy szerkezet) és a (ha T₀ osztály) alaposztályai T₀ .T₀ A rendszer csak akkor ad hozzá típust a készlethez D , 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, amelyekben D 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 foglalja Tazt. Ha U ü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ő helyen U:
    • Ha az S létezik, és a konvertált USoperátorok bármelyike, akkor Sₓ az .S
    • Ellenkező esetben, ha a konvertált operátorok bármelyike olyan típusokból konvertálódik, amelyek magukban U foglalják Eazokat, akkor Sₓ 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.
  • Keresse meg az operátorok legspecifikusabb céltípusát Tₓa következő helyen U:
    • Ha a konvertált UToperátorok bármelyike , akkor Tₓ az .T
    • Ellenkező esetben, ha a konvertált operátorok U bármelyike olyan típussá alakul át, amely Tmagában foglalja azokat, akkor Tₓ 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átorok Ucé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.
  • 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ér Sₓ a konvertálásra Tₓ, 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.
  • Végül alkalmazza az átalakítást:
    • Ha E még nem rendelkezik ilyen típussal, akkor az E Sₓ típusból Sₓ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ₓ nem T, akkor a szokásos explicit átalakítás TₓT lesz végrehajtva.

A felhasználó által definiált explicit átalakítás típusról típusra ST 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 ST?
  • 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éke false), akkor az eredmény a típus T?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ást ST a következőre, majd a sortörést T a következőreT?.
  • Ha a null értékű átalakítás a következőre ST?történik, a rendszer az átalakítást a mögöttes átalakításként ST értékeli ki, amelyet egy sortörés TT? 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ént TS? értékeli ki, majd az alapul szolgáló átalakításból a S 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 Tkonvertá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 ST a hozzá való körbefuttatás TT?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, akkor DF ugyanazzal a paraméterszámmal kell rendelkeznie.
  • Ha F nem tartalmaz anonymous_function_signature, akkor D nulla vagy több bármilyen típusú paraméter lehet, feltéve, hogy a kimeneti paraméter egyik paramétere D sem.
  • Ha F explicit módon beírt paraméterlistával rendelkezik, minden paraméterben D ugyanazok a módosítók szerepelnek, mint a megfelelő paraméterben F , és a megfelelő paraméter Fkö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, és D visszatérési típussal rendelkezik «TaskType» (15.14.1. §), akkor amikor az egyes paraméterek F a megfelelő paraméter Dtípusát adják meg, akkor a törzse F egy érvényes kifejezés (w.r.t §12), amely statement_expression lenne engedélyezve (13.7. §).
  • Ha a törzs F egy blokk, ésDvagy üres visszatérési típussal aszinkron, és F visszatérési típussal rendelkezikD, akkor amikor az egyes paraméterek «TaskType» a megfelelő paraméter Ftípusát adják meg, a törzs D egy érvényes blokk (w.r.t F), amelyben egyetlen utasítás sem határoz meg kifejezést.
  • Ha a törzs F egy kifejezés, és akárF nem aszinkron és D nem rendelkezik void visszatérési T típussal, vagyF aszinkron és D rendelkezik «TaskType»<T> visszatérési típussal (15.14.1. §), akkor ha F minden egyes paramétere a megfelelő D paraméter típusát kapja meg, a törzs F 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, és D nem érvénytelen visszatérési típussal Trendelkezik, vagyF aszinkron, és D visszatérési típussal rendelkezik «TaskType»<T> , akkor amikor az egyes paraméterek F a megfelelő paraméter Dtípusát adják meg, akkor a törzs F 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ó Tkifejezé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ípus A argumentumát veszi fel, és egy típusértéket Rad 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ípus xintesetén x + 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ípusx + 1) eredménye int 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énye x + 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 + 1eredménye int implicit módon konvertálható az aszinkron lambda tényleges visszatérési típusáraint, amelynek visszatérési típusa Task<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 nullcé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 Dmegfelelő 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 (outvagy ref) a parameter_listD , kivéve a típusparamétereketdynamic, ahol a megfelelő kifejezés típusa object helyett dynamica 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 á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és E 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és F 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 Eexplicit 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 Etá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 egy System.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.