Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
10.1 Allmänt
En konvertering gör att ett uttryck konverteras till eller behandlas som av en viss typ. I det tidigare fallet kan en konvertering innebära en ändring i representationen. Konverteringar kan vara implicita eller explicita, och detta avgör om en explicit gjutning krävs.
Exempel: Till exempel är konverteringen från typ
inttill typlongimplicit, så uttryck av typenintkan implicit behandlas som typlong. Den motsatta konverteringen, från typlongtill typint, är explicit och därför krävs en explicit gjutning.int a = 123; long b = a; // implicit conversion from int to long int c = (int) b; // explicit conversion from long to intslutexempel
Vissa konverteringar definieras av språket. Program kan också definiera sina egna konverteringar (§10.5).
Vissa konverteringar på språket definieras från uttryck till typer, andra från typer till typer. En konvertering från en typ gäller för alla uttryck som har den typen.
Exempel:
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;slutexempel
10.2 Implicita konverteringar
10.2.1 Allmänt
Följande konverteringar klassificeras som implicita konverteringar:
- Identitetskonverteringar (§10.2.2)
- Implicita numeriska konverteringar (§10.2.3)
- Implicit uppräkningskonverteringar (§10.2.4)
- Implicita interpolerade strängkonverteringar (§10.2.5)
- Implicita referenskonverteringar (§10.2.8)
- Boxningskonverteringar (§10.2.9)
- Implicita dynamiska konverteringar (§10.2.10)
- Implicit typparameterkonverteringar (§10.2.12)
- Implicita konverteringar av konstanta uttryck (§10.2.11)
- Användardefinierade (inklusive hävda) implicita konverteringar (§10.2.14)
- Anonyma funktionskonverteringar (§10.2.15)
- Metodgruppkonverteringar (§10.2.15)
- Nullliterala konverteringar (§10.2.7)
- Implicita nullbara konverteringar (§10.2.6)
- Implicita tupppelkonverteringar (§10.2.13)
- Standardliterala konverteringar (§10.2.16)
- Implicita kastkonverteringar (§10.2.17)
Implicita konverteringar kan ske i en mängd olika situationer, inklusive funktionsmedlemsanrop (§12.6.6), gjutna uttryck (§12.9.8) och tilldelningar (§12.22).
De fördefinierade implicita konverteringarna lyckas alltid och orsakar aldrig undantag.
Obs! Korrekt utformade användardefinierade implicita konverteringar bör också uppvisa dessa egenskaper. slutkommentar
I konverteringssyfte är typerna object och dynamic identitetskonverterbara (§10.2.2).
Dynamiska konverteringar (§10.2.10) gäller dock endast för uttryck av typen dynamic (§8.2.4).
10.2.2 Identitetskonvertering
En identitetskonvertering konverterar från valfri typ till samma typ eller en typ som är likvärdig vid körning. En anledning till att konverteringen finns är att en typ T eller ett uttryck av typen T kan sägas vara konvertibel till T sig själv. Följande identitetskonverteringar finns:
- Mellan TochT, för alla typerT.
- Mellan TochT?för alla referenstyperT.
- Mellan objectochdynamic.
- Mellan alla tuppelns typer med samma aritet och motsvarande konstruerade typ, när det finns en identitetskonvertering ValueTuple<...>mellan varje par av motsvarande elementtyper.
- Mellan typer som konstruerats av samma generiska typ där det finns en identitetskonvertering mellan varje motsvarande typargument.
Exempel: Följande illustrerar den tredje regelns rekursiva karaktär:
(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;Typerna av tupplar
t1,t2ocht3alla har två element: enintföljt av enstring. Tuppelns elementtyper kan själva utföras av tupplar, som it4,t5ocht6. Det finns en identitetskonvertering mellan varje par av motsvarande elementtyper, inklusive kapslade tupplar, och därför finns det en identitetskonvertering mellan typerna av tupplart4,t5ocht6.slutexempel
Alla identitetskonverteringar är symmetriska. Om det finns en identitetskonvertering från T₁ till T₂finns det en identitetskonvertering från T₂ till T₁. Två typer är identitetskonverterbara när det finns en identitetskonvertering mellan två typer.
I de flesta fall har en identitetskonvertering ingen effekt vid körning. Men eftersom flyttalsoperationer kan utföras med högre precision än vad som föreskrivs i deras typ (§8.3.7), kan tilldelningen av deras resultat leda till en förlust av precision, och explicita avgjutningar garanteras att minska precisionen till vad som föreskrivs av typen (§12.9.8).
10.2.3 Implicita numeriska konverteringar
De implicita numeriska konverteringarna är:
- Från sbytetillshort,int,long,float,doubleellerdecimal.
- Från bytetillshort,ushort,int,uint,long,ulong,float, ellerdoubledecimal.
- Från shorttillint,long,float,doubleellerdecimal.
- Från ushorttillint,uint,long,ulong,float,doubleellerdecimal.
- Från inttilllong,float,doubleellerdecimal.
- Från uinttilllong,ulong,float,doubleellerdecimal.
- Från longtillfloat,doubleellerdecimal.
- Från ulongtillfloat,doubleellerdecimal.
- Från chartillushort,int,uint,long,ulong,float,doubleellerdecimal.
- Från floattilldouble.
Konverteringar från int, uint, long eller ulong till float och från long eller ulong till double kan orsaka en förlust av precision, men kommer aldrig att orsaka en förlust av omfattning. De andra implicita numeriska konverteringarna förlorar aldrig någon information.
Det finns inga fördefinierade implicita konverteringar till char typen, så värden för de andra integraltyperna konverteras inte automatiskt till char typen.
10.2.4 Implicit uppräkningskonverteringar
En implicit uppräkningskonvertering tillåter att en constant_expression (§12.24) med någon heltalstyp och värdet noll konverteras till alla enum_type och till alla nullable_value_type vars underliggande typ är en enum_type. I det senare fallet utvärderas konverteringen genom att konvertera till den underliggande enum_type och omsluta resultatet (§8.3.12).
10.2.5 Implicita interpolerade strängkonverteringar
En implicit interpolerad strängkonvertering tillåter att en interpolated_string_expression (§12.8.3) konverteras till System.IFormattable eller System.FormattableString (som implementerar System.IFormattable).
När den här konverteringen tillämpas består inte ett strängvärde från den interpolerade strängen. I stället skapas en instans av System.FormattableString , enligt beskrivningen i §12.8.3.
10.2.6 Implicita nullbara konverteringar
De implicita nullbara konverteringarna är de nullbara konverteringar (§10.6.1) som härleds från implicita fördefinierade konverteringar.
10.2.7 Nullliterala konverteringar
Det finns en implicit konvertering från literalen null till en referenstyp eller nullbar värdetyp. Den här konverteringen ger en null-referens om måltypen är en referenstyp eller nullvärdet (§8.3.12) för den angivna nullbara värdetypen.
10.2.8 Implicita referenskonverteringar
De implicita referenskonverteringarna är:
- Från alla reference_type till objectochdynamic.
- Från alla  till alla S, som tillhandahålls härleds frånT.
- Från alla class_typeStill alla interface_typeT, tillhandahållnaSimplementerarT.
- Från alla  till alla S, som tillhandahålls härleds frånT.
- Från en array_typeSmed en elementtypSᵢtill en array_typeTmed en elementtypTᵢ, förutsatt att allt följande är sant:- 
              SochTskiljer sig endast i elementtyp. Med andra ord ochSThar samma antal dimensioner.
- Det finns en implicit referenskonvertering från SᵢtillTᵢ.
 
- 
              
- Från en endimensionell matristyp S[]tillSystem.Collections.Generic.IList<T>,System.Collections.Generic.IReadOnlyList<T>och deras basgränssnitt, förutsatt att det finns en implicit identitet eller referenskonvertering frånStillT.
- Från alla array_type till System.Arrayoch de gränssnitt som implementeras.
- Från alla delegate_type till System.Delegateoch de gränssnitt som implementeras.
- Från nullliteralen (§6.4.5.7) till alla referenstyper.
- Från alla
- Från alla reference_type till ett gränssnitt eller en ombudstyp Tom den har en implicit identitet eller referenskonvertering till ett gränssnitt eller en ombudstypT₀ochT₀är varianskonverterad (§19.2.3.3) tillT.
- Implicita konverteringar som omfattar typparametrar som är kända för att vara referenstyper. Mer information om implicita konverteringar med typparametrar finns i §10.2.12 .
Implicita referenskonverteringar är de konverteringar mellan reference_typesom alltid kan bevisas lyckas och därför inte kräver några kontroller vid körning.
Referenskonverteringar, implicita eller explicita, ändrar aldrig referensidentiteten för objektet som konverteras.
Obs! Med andra ord, även om en referenskonvertering kan ändra referenstypen, ändras aldrig typen eller värdet för det objekt som refereras till. slutkommentar
10.2.9 Boxningskonverteringar
En boxningskonvertering tillåter att en value_type implicit konverteras till en reference_type. Följande boxningskonverteringar finns:
- Från valfri value_type till typen object.
- Från valfri value_type till typen System.ValueType.
- Från valfri enum_type till typen System.Enum.
- Från alla non_nullable_value_type till alla interface_type som implementeras av non_nullable_value_type.
- Från alla
- Från alla non_nullable_value_type till alla interface_typeIså att det finns en boxningskonvertering från non_nullable_value_type till en annan interface_typeI₀, ochI₀är varians-cabriolet (§19.2.3.3) tillI.
- Från alla nullable_value_type till alla reference_type där det finns en boxningskonvertering från den underliggande typen av nullable_value_type till reference_type.
- Från en typparameter som inte är känd för att vara en referenstyp till någon typ så att konverteringen tillåts av §10.2.12.
Boxning av ett värde av typen icke-nullable-value-består av att allokera en objektinstans och kopiera värdet till den instansen.
Boxning av ett värde för en nullable_value_type ger en null-referens om det är null-värdet (HasValue är falskt), eller resultatet av att packa upp och boxa det underliggande värdet annars.
Obs! Boxningsprocessen kan föreställas när det gäller förekomsten av en boxningsklass för varje värdetyp. Överväg till exempel att implementera ett
struct SgränssnittI, med en boxningsklass med namnetS_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(); } }Boxning av ett värde
vav typenSbestår nu av att köra uttrycketnew S_Boxing(v)och returnera den resulterande instansen som ett värde för konverteringens måltyp. Det innebär att påståendenaS s = new S(); object box = s;kan ses som liknar:
S s = new S(); object box = new S_Boxing(s);Den inbillade boxningstypen som beskrivs ovan finns faktiskt inte. I stället har ett boxat värde av typen
SkörningstypS, och en körningstypkontroll med operatornismed en värdetyp som den högra operanden testar om den vänstra operanden är en boxad version av den högra operanden. Ett exempel:int i = 123; object box = i; if (box is int) { Console.Write("Box contains an int"); }kommer att mata ut följande:
Box contains an intEn boxningskonvertering innebär att en kopia av värdet boxas. Detta skiljer sig från en konvertering av en reference_type för att skriva
object, där värdet fortsätter att referera till samma instans och helt enkelt betraktas som den mindre härledda typenobject. Följande är till exempelstruct 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); } }matar ut värdet 10 i konsolen eftersom den implicita boxningsåtgärd som inträffar i tilldelningen av
ptillboxgör att värdetpför kopieras. HadePointdeklarerats som enclassi stället skulle värdet 20 vara utdata eftersompochboxrefererar till samma instans.Analogi av en boxning klass bör inte användas som mer än ett användbart verktyg för att föreställa sig hur boxning fungerar konceptuellt. Det finns många subtila skillnader mellan beteendet som beskrivs i den här specifikationen och det beteende som skulle bli resultatet av att boxning implementeras på just detta sätt.
slutkommentar
10.2.10 Implicita dynamiska konverteringar
Det finns en implicit dynamisk konvertering från ett uttryck av typen dynamisk till valfri typ T. Konverteringen är dynamiskt bunden §12.3.3, vilket innebär att en implicit konvertering söks vid körning från körningstypen för uttrycket till T. Om ingen konvertering hittas utlöses ett körningsfel.
Denna implicita konvertering strider till synes mot rådet i början av §10.2 att en implicit konvertering aldrig ska orsaka ett undantag. Det är dock inte själva konverteringen , utan resultatet av konverteringen som orsakar undantaget. Risken för körningsfel är en naturlig del av användningen av dynamisk bindning. Om dynamisk bindning av konverteringen inte önskas kan uttrycket först konverteras till objectoch sedan till önskad typ.
Exempel: Följande illustrerar implicita dynamiska konverteringar:
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 existsTilldelningarna till
s2ochibåda använder implicita dynamiska konverteringar, där bindningen av åtgärderna pausas fram till körning. Vid körning söks implicita konverteringar från körningstypend(string) till måltypen. En konvertering hittas tillstringmen inte tillint.slutexempel
10.2.11 Implicita konverteringar av konstanta uttryck
En implicit konvertering av konstanta uttryck tillåter följande konverteringar:
- En constant_expression (§12.24) av typen intkan konverteras till typensbyte, ,byteshort,ushort,uintellerulong, förutsatt att värdet för constant_expression ligger inom måltypens intervall.
- En constant_expression av typen  kan konverteras till typen long, förutsatt att värdet förulonginte är negativt.
10.2.12 Implicita konverteringar med typparametrar
För en  som är känd för att vara en referenstyp (T) finns följande implicita referenskonverteringar (§10.2.8):
- Från Ttill dess effektiva basklassC, frånTtill valfri basklass avC, och frånTtill alla gränssnitt som implementeras avC.
- Från Ttill en interface_typeIiTden effektiva gränssnittsuppsättningen och frånTtill valfritt basgränssnitt förI.
- Från Ttill en typparameterUsomTär beroende avU(§15.2.5).Obs! Eftersom Tär känt som en referenstyp är körningstypenTalltid en referenstyp inom omfångetUför , även omUdet inte är känt att den är en referenstyp vid kompileringstid. slutkommentar
- Från nulllitralen (§6.4.5.7) till T.
För en type_parameterT som inte är känd för att vara en referenstyp §15.2.5 anses följande konverteringar som involverar T vara boxningskonverteringar (§10.2.9) vid kompileringstid. Vid körning, om T är en värdetyp, körs konverteringen som en boxningskonvertering. Vid körning, om T är en referenstyp, körs konverteringen som en implicit referenskonvertering eller identitetskonvertering.
- Från Ttill dess effektiva basklassC, frånTtill valfri basklass avC, och frånTtill alla gränssnitt som implementeras avC.Obs! kommer att vara en av typerna C,System.ObjectellerSystem.ValueType(annarsSystem.Enumskulle vara känd för att vara en referenstyp).Tslutkommentar
- Från Ttill en interface_typeIiTden effektiva gränssnittsuppsättningen och frånTtill valfritt basgränssnitt förI.
För en  som inteTkänd för att vara en referenstyp finns det en implicit konvertering från  till en typparameter T som anges U beror på T. Vid körning, om T är en värdetyp och U är en referenstyp, körs konverteringen som en boxningskonvertering. Vid körning, om både T och U är värdetyper, så T är och U nödvändigtvis samma typ och ingen konvertering utförs. Vid körning, om T är en referenstyp, är det U nödvändigtvis också en referenstyp och konverteringen körs som en implicit referenskonvertering eller identitetskonvertering (§15.2.5).
Följande ytterligare implicita konverteringar finns för en viss typparameter T:
- Från Ttill en referenstypSom den har en implicit konvertering till en referenstypS₀ochS₀har en identitetskonvertering tillS. Vid körning körs konverteringen på samma sätt som konverteringen tillS₀.
- Från Ttill en gränssnittstypIom den har en implicit konvertering till en gränssnittstypI₀ochI₀är varianskonverterad tillI(§19.2.3.3). Vid körning, omTär en värdetyp, körs konverteringen som en boxningskonvertering. Annars körs konverteringen som en implicit referenskonvertering eller identitetskonvertering.
I samtliga fall säkerställer reglerna att en konvertering körs som en boxningskonvertering om och endast om konverteringen vid körningen är från en värdetyp till en referenstyp.
10.2.13 Implicita tupppelkonverteringar
Det finns en implicit konvertering från ett tupppeluttryck E till en tuppelns typ T om E har samma aritet som T och en implicit konvertering finns från varje element i E till motsvarande elementtyp i T. Konverteringen utförs genom att skapa en instans av Tmotsvarande System.ValueTuple<...> typ och initiera vart och ett av dess fält i ordning från vänster till höger genom att utvärdera motsvarande tuppelns elementuttryck E, konvertera det till motsvarande elementtyp med hjälp av T den implicita konverteringen som hittades och initiera fältet med resultatet.
Om ett elementnamn i tuppelns uttryck inte matchar ett motsvarande elementnamn i tuppelns typ, ska en varning utfärdas.
Exempel:
(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 ignoredDeklarationerna för
t1,t2t4ocht5är alla giltiga, eftersom implicita konverteringar finns från elementuttrycken till motsvarande elementtyper. Deklarationen avt3är ogiltig eftersom det inte finns någon konvertering frånnulltillint. Deklarationen avt5orsakar en varning eftersom elementnamnen i tuppelns uttryck skiljer sig från dem i tuppelns typ.slutexempel
10.2.14 Användardefinierade implicita konverteringar
En användardefinierad implicit konvertering består av en valfri implicit standardkonvertering följt av körning av en användardefinierad implicit konverteringsoperator följt av en annan valfri implicit standardkonvertering. De exakta reglerna för utvärdering av användardefinierade implicita konverteringar beskrivs i §10.5.4.
10.2.15 Anonyma funktionskonverteringar och metodgruppkonverteringar
Anonyma funktioner och metodgrupper har inte typer i sig själva, men de kan implicit konverteras till delegerade typer. Dessutom kan vissa lambda-uttryck implicit konverteras till uttrycksträdstyper. Anonyma funktionskonverteringar beskrivs mer detaljerat i §10.7 och metodgruppkonverteringar i §10.8.
10.2.16 Standardliterala konverteringar
Det finns en implicit konvertering från en default_literal (§12.8.21) till vilken typ som helst. Den här konverteringen genererar standardvärdet (§9.3) av den härledda typen.
10.2.17 Implicita kastkonverteringar
Även om utkastsuttryck inte har någon typ kan de implicit konverteras till valfri typ.
10.3 Explicita konverteringar
10.3.1 Allmänt
Följande konverteringar klassificeras som explicita konverteringar:
- Alla implicita konverteringar (§10.2)
- Explicita numeriska konverteringar (§10.3.2)
- Explicita uppräkningskonverteringar (§10.3.3)
- Explicita nullbara konverteringar (§10.3.4)
- Explicita tupppelkonverteringar (§10.3.6)
- Explicita referenskonverteringar (§10.3.5)
- Explicita gränssnittskonverteringar
- Avboxning av konverteringar (§10.3.7)
- Explicita typparameterkonverteringar (§10.3.8)
- Användardefinierade explicita konverteringar (§10.3.9)
Explicita konverteringar kan ske i gjutna uttryck (§12.9.8).
Uppsättningen explicita konverteringar innehåller alla implicita konverteringar.
Obs! Detta gör till exempel att en explicit gjutning kan användas när det finns en implicit identitetskonvertering för att tvinga valet av en viss metodöverbelastning. slutkommentar
Explicita konverteringar som inte är implicita konverteringar är konverteringar som inte alltid kan bevisas lyckas, konverteringar som är kända för att förlora information och konverteringar mellan domäner av typer som är tillräckligt olika för att förtjäna explicit notation.
10.3.2 Explicita numeriska konverteringar
De explicita numeriska konverteringarna är konverteringarna från en numeric_type till en annan numeric_type för vilka en implicit numerisk konvertering (§10.2.3) inte redan finns:
- Från sbytetillbyte,ushort,uint,ulongellerchar.
- Från bytetillsbyteellerchar.
- Från shorttillsbyte,byte,ushort,uint,ulongellerchar.
- Från ushorttillsbyte,byte,shortellerchar.
- Från inttillsbyte,byte,short,ushort,uint,ulongellerchar.
- Från uinttillsbyte,byte,short,ushort,intellerchar.
- Från longtillsbyte,byte,short,ushort,int,uint,ulongellerchar.
- Från ulongtillsbyte,byte,short,ushort,int,uint,longellerchar.
- Från chartillsbyte,byteellershort.
- Från floattillsbyte,byte,short,ushort,int,uint,long,ulong, ,charellerdecimal.
- Från doubletillsbyte,byte,short,ushort,int,uint,long,ulong,char, ,floatellerdecimal.
- Från decimaltillsbyte,byte,short,ushort,int,uint,long,ulong,char, ,floatellerdouble.
Eftersom de explicita konverteringarna omfattar alla implicita och explicita numeriska konverteringar är det alltid möjligt att konvertera från alla numeric_type till andra numeric_type med ett gjutet uttryck (§12.9.8).
De explicita numeriska konverteringarna kan förlora information eller eventuellt orsaka att undantag utlöses. En explicit numerisk konvertering bearbetas på följande sätt:
- För en konvertering från en integrerad typ till en annan integrerad typ beror bearbetningen på överflödets kontrollkontext (§12.8.20) där konverteringen äger rum: - I ett checkedsammanhang lyckas konverteringen om värdet för källoperatorn ligger inom måltypens intervall, men genererar ettSystem.OverflowExceptionom värdet för källoperatorn ligger utanför måltypens intervall.
- I ett uncheckedsammanhang lyckas konverteringen alltid och fortsätter på följande sätt.- Om källtypen är större än måltypen trunkeras källvärdet genom att dess "extra" viktigaste bitar ignoreras. Resultatet behandlas sedan som ett värde av måltypen.
- Om källtypen har samma storlek som måltypen behandlas källvärdet som ett värde av måltypen
 
 
- I ett 
- För en konvertering från decimaltill en integrerad typ avrundas källvärdet mot noll till närmaste integralvärde, och det här integralvärdet blir resultatet av konverteringen. Om det resulterande integralvärdet ligger utanför måltypens intervall genereras ettSystem.OverflowException.
- För en konvertering från floatellerdoubletill en integrerad typ beror bearbetningen på överflödeskontrollkontexten (§12.8.20) där konverteringen äger rum:- I en kontrollerad kontext fortsätter konverteringen enligt följande: - Om operandvärdet är NaN eller oändligt genereras en System.OverflowException.
- Annars avrundas källoperatorn mot noll till närmaste integralvärde. Om det här integralvärdet ligger inom måltypens intervall är det här värdet resultatet av konverteringen.
- Annars kastas en System.OverflowException.
 
- Om operandvärdet är NaN eller oändligt genereras en 
- I en omarkerad kontext lyckas konverteringen alltid och fortsätter enligt följande.
- Om värdet för operanden är NaN eller oändligt är resultatet av konverteringen ett ospecificerat värde av måltypen.
- Annars avrundas källoperatorn mot noll till närmaste integralvärde. Om det här integralvärdet ligger inom måltypens intervall är det här värdet resultatet av konverteringen.
- Annars är resultatet av konverteringen ett ospecificerat värde för måltypen.
 
 
- I en kontrollerad kontext fortsätter konverteringen enligt följande: 
- För en konvertering från doubletillfloatdoubleavrundas värdet till närmastefloatvärde. Om värdetdoubleär för litet för att representeras som ettfloatblir resultatet noll med samma tecken som värdet. Om värdetsdoublestorlek är för stor för att representeras som enfloatblir resultatet oändligt med samma tecken som värdet. Om värdetdoubleär NaN blir resultatet även NaN.
- För en konvertering från floatellerdoubletilldecimalkonverteras källvärdet tilldecimalrepresentation och avrundas till närmaste tal vid behov (§8.3.8).- Om källvärdet är för litet för att representeras som ett decimalblir resultatet noll, vilket bevarar tecknet för det ursprungliga värdet omdecimaldet stöder signerade nollvärden.
- Om källvärdets storlek är för stor för att representeras som ett decimal, eller om värdet är oändligt, är resultatet oändligheten som bevarar tecknet för det ursprungliga värdet, om decimalrepresentationen stöder infiniteter, annars genereras en System.OverflowException.
- Om källvärdet är NaN blir resultatet NaN om decimalrepresentationen stöder NaN. annars genereras en System.OverflowException.
 
- Om källvärdet är för litet för att representeras som ett 
- För en konvertering från decimaltillfloatellerdoubledecimalavrundas värdet till närmastedoublevärde ellerfloatvärde. Om källvärdets storlek är för stor för att representeras i måltypen, eller om värdet är oändligt, blir resultatet oändligheten som bevarar tecknet för det ursprungliga värdet. Om källvärdet är NaN blir resultatet NaN. Även om den här konverteringen kan förlora precisionen orsakar den aldrig ett undantagsfel.
Obs! Typen
decimalkrävs inte för att stödja infiniteter eller NaN-värden, men kan göra det. Dess intervall kan vara mindre än intervalletfloatför ochdouble, men är inte garanterat. Fördecimalrepresentationer utan infiniteter eller NaN-värden, och med ett intervall som är mindre änfloat, blir resultatet av en konvertering fråndecimaltill antingenfloatellerdoublealdrig oändlighet eller NaN. slutkommentar
10.3.3 Explicit uppräkningskonverteringar
De explicita uppräkningskonverteringarna är:
- Från sbyte,byte,short,ushort,int,uint,long,ulong,char,float, ,doubleellerdecimaltill någon enum_type.
- Från alla enum_type till sbyte,byte,shortushort, ,int,uint,long,ulong, ,char,float, ,doubleellerdecimal.
- Från alla enum_type till andra enum_type.
En explicit uppräkningskonvertering mellan två typer bearbetas genom att alla deltagande enum_type behandlas som den underliggande typen av enum_type och sedan utföra en implicit eller explicit numerisk konvertering mellan de resulterande typerna.
Exempel: Med en enum_type
Emed en underliggande typ avintbearbetas en konvertering frånEtillbytesom en explicit numerisk konvertering (§10.3.2) fråninttillbyteoch en konvertering frånbytetillEbearbetas som en implicit numerisk konvertering (§10.2.3) frånbytetillint. slutexempel
10.3.4 Explicita nullbara konverteringar
De explicita nullbara konverteringarna är de nullbara konverteringar (§10.6.1) som härleds från explicita och implicita fördefinierade konverteringar.
10.3.5 Explicita referenskonverteringar
De explicita referenskonverteringarna är:
- Från objekt till andra reference_type.
- Från alla  till alla S, som tillhandahålls är en basklass förT.
- Från alla  till alla S, tillhandahållsTinte är förseglad och tillhandahållsSinte implementerarS.
- Från alla  till alla S, tillhandahållsTinte är förseglade eller tillhandahållnaTTredskap .
- Från alla  till alla S, som tillhandahålls härleds inte frånT.
- Från en array_typeSmed en elementtypSᵢtill en array_typeTmed en elementtypTᵢ, förutsatt att allt följande är sant:- 
              SochTskiljer sig endast i elementtyp. Med andra ord ochSThar samma antal dimensioner.
- Det finns en explicit referenskonvertering från SᵢtillTᵢ.
 
- 
              
- Från System.Arrayoch de gränssnitt som implementeras, till alla array_type.
- Från en endimensionell array_type  till , och dess basgränssnitt, förutsatt att det finns en identitetskonvertering eller explicit referenskonvertering från S[]tillSystem.Collections.Generic.IList<T>.System.Collections.Generic.IReadOnlyList<T>ST
- Från System.Collections.Generic.IList<S>,System.Collections.Generic.IReadOnlyList<S>och deras basgränssnitt till en endimensionell matristypT[], förutsatt att det finns en identitetskonvertering eller explicit referenskonvertering frånStill T.
- Från System.Delegateoch de gränssnitt som implementeras till alla delegate_type.
- Från en referenstyp Still en referenstypTom den har en explicit referenskonvertering frånStill en referenstypT₀ochT₀det finns en identitetskonvertering frånT₀tillT.
- Från en referenstyp Still ett gränssnitt eller en ombudstypTom det finns en explicit referenskonvertering frånStill ett gränssnitt eller en ombudstypT₀och antingenT₀är varianskonverterad tillTellerTär varianskonverterad tillT₀§19.2.3.3.
- Från D<S₁...Sᵥ>tillD<T₁...Tᵥ>därD<X₁...Xᵥ>är en allmän ombudstyp,D<S₁...Sᵥ>är inte kompatibel med eller identiskD<T₁...Tᵥ>med , och för varje typparameterXᵢavDföljande undantag:- Om Xᵢär invariant är detSᵢidentiskt medTᵢ.
- Om Xᵢär covariant finns det en identitetskonvertering, implicit referenskonvertering eller explicit referenskonvertering frånSᵢtillTᵢ.
- Om Xᵢär kontravariantSᵢär deTᵢantingen identiska eller båda referenstyperna.
 
- Om 
- Explicita konverteringar med typparametrar som är kända för att vara referenstyper. Mer information om explicita konverteringar med typparametrar finns i §10.3.8.
De explicita referenskonverteringarna är de konverteringar mellan reference_typesom kräver körningskontroller för att säkerställa att de är korrekta.
För att en explicit referenskonvertering ska lyckas vid körning ska värdet för källoperatorn vara null, eller så ska typen av objektet som refereras av källoperatorn vara en typ som kan konverteras till måltypen genom en implicit referenskonvertering (§10.2.8). Om en explicit referenskonvertering misslyckas genereras en System.InvalidCastException .
Obs! Referenskonverteringar, implicita eller explicita, ändrar aldrig själva referensvärdet (§8.2.1), endast dess typ. Det ändrar inte heller typen eller värdet för det objekt som refereras till. slutkommentar
10.3.6 Explicita tupplar
Det finns en explicit konvertering från ett tupppeluttryck E till en tuppelns typ T om E det finns samma aritet som T och det finns en implicit eller explicit konvertering från varje element i E till motsvarande elementtyp i T. Konverteringen utförs genom att skapa en instans av Tmotsvarande System.ValueTuple<...> typ och initiera vart och ett av dess fält i ordning från vänster till höger genom att utvärdera motsvarande tuppelns elementuttryck E, konvertera det till motsvarande elementtyp med hjälp av T den explicita konverteringen som hittades och initiera fältet med resultatet.
10.3.7 Avboxningskonverteringar
En konvertering med avboxning gör att en reference_type uttryckligen kan konverteras till en value_type. Följande konverteringar för avboxning finns:
- Från typen objecttill valfri value_type.
- Från typen System.ValueTypetill valfri value_type.
- Från typen System.Enumtill valfri enum_type.
- Från alla interface_type till alla non_nullable_value_type som implementerar interface_type.
- Från alla  till alla Idär det finns en avboxningskonvertering från en interface_type tillI₀och en identitetskonvertering från tillI.
- Från alla interface_typeItill alla non_nullable_value_type där det sker en avboxningskonvertering från en interface_typeI₀till non_nullable_value_type och antingenI₀är variance_convertible tillIellerIär varianskonverterad tillI₀(§19.2.3.3).
- Från alla reference_type till alla nullable_value_type där det finns en avboxningskonvertering från reference_type till nullable_value_type underliggande non_nullable_value_type.
- Från en typparameter som inte är känd för att vara en värdetyp till någon typ så att konverteringen tillåts av §10.3.8.
En avboxningsåtgärd till en non_nullable_value_type består av att först kontrollera att objektinstansen är ett boxat värde för den angivna non_nullable_value_type och sedan kopiera värdet från instansen.
Om du avboxar till en nullable_value_type genereras värdet null för nullable_value_type om källoperatorn är null, eller det omslutna resultatet av att ta bort instansen av objektet till den underliggande typen av nullable_value_type annat.
Obs! Med hänvisning till den imaginära boxningsklassen som beskrivs i §10.2.9 består en konvertering av en objektruta till en value_type
Sav att köra uttrycket((S_Boxing)box).value. Det innebär att påståendenaobject box = new S(); S s = (S)box;motsvarar konceptuellt
object box = new S_Boxing(new S()); S s = ((S_Boxing)box).value;slutkommentar
För en avboxningskonvertering till en viss non_nullable_value_type ska lyckas vid körning ska värdet för källoperatorn vara en referens till ett boxat värde för den non_nullable_value_type. Om källoperatorn är null en System.NullReferenceException utlöses. Om källoperatorn är en referens till ett inkompatibelt objekt genereras en System.InvalidCastException .
För en avboxningskonvertering till en viss nullable_value_type ska lyckas vid körningen ska värdet för källoperatorn vara antingen null eller en referens till ett boxat värde för den underliggande non_nullable_value_type för nullable_value_type. Om källoperatorn är en referens till ett inkompatibelt objekt genereras en System.InvalidCastException .
10.3.8 Explicita konverteringar med typparametrar
För en  som är känd för att vara en referenstyp (T) finns följande explicita referenskonverteringar (§10.3.5):
- Från den effektiva basklassen CTför tillToch från valfri basklassCtillT.
- Från alla interface_type till T.
- Från Ttill alla interface_typeIförutsatt att det inte redan finns en implicit referenskonvertering frånTtillI.
- Från en  till UsomTär beroende avT(U).Obs! Eftersom Tär känd för att vara en referenstyp, inom omfångetTför , kommer körningstypen för dig alltid att vara en referenstyp, även omUdet inte är känt att vara en referenstyp vid kompileringstid. slutkommentar
För en type_parameterT som inte är känd för att vara en referenstyp (§15.2.5), anses följande konverteringar som involverar T vara unboxing-konverteringar (§10.3.7) vid kompileringstid. Vid körning, om T är en värdetyp, körs konverteringen som en konvertering som avboxas. Vid körning, om T är en referenstyp, körs konverteringen som en explicit referenskonvertering eller identitetskonvertering.
- Från den effektiva basklassen CTför tillToch från valfri basklassCtillT.Obs! C är en av typerna System.Object,System.ValueTypeellerSystem.Enum(annarsTär det känt att det är en referenstyp). slutkommentar
- Från alla interface_type till T.
För en type_parameterT som inte är känd för att vara en referenstyp (§15.2.5) finns följande explicita konverteringar:
- Från Ttill alla interface_typeIförutsatt att det inte redan finns en implicit konvertering frånTtillI. Denna konvertering består av en implicit boxningskonvertering (§10.2.9) frånTtillobjectföljt av en explicit referenskonvertering frånobjecttillI. Vid körning, omTär en värdetyp, körs konverteringen som en boxningskonvertering följt av en explicit referenskonvertering. Vid körning, omTär en referenstyp, körs konverteringen som en explicit referenskonvertering.
- Från en typparameter Utill angivet somTärTberoende av (U). Vid körning, omTär en värdetyp ochUär en referenstyp, körs konverteringen som en konvertering som avboxas. Vid körning, om bådeTochUär värdetyper, såTär ochUnödvändigtvis samma typ och ingen konvertering utförs. Vid körning, omTär en referenstyp, är detUnödvändigtvis också en referenstyp och konverteringen körs som en explicit referenskonvertering eller identitetskonvertering.
I samtliga fall säkerställer reglerna att en konvertering körs som en konvertering utan inkorg om och endast om konverteringen vid körningen är från en referenstyp till en värdetyp.
Ovanstående regler tillåter inte en direkt explicit konvertering från en icke-tränad typparameter till en icke-gränssnittstyp, vilket kan vara överraskande. Anledningen till denna regel är att förhindra förvirring och göra semantiken för sådana konverteringar tydliga.
Exempel: Överväg följande deklaration:
class X<T> { public static long F(T t) { return (long)t; // Error } }Om den direkta explicita konverteringen av
ttilllongvar tillåten kan man enkelt förvänta sig att detX<int>.F(7)skulle returnera7L. Det skulle det dock inte göra, eftersom de numeriska standardkonverteringarna endast beaktas när typerna är kända för att vara numeriska vid bindningstid. För att semantiken ska bli tydlig måste exemplet ovan i stället skrivas:class X<T> { public static long F(T t) { return (long)(object)t; // Ok, but will only work when T is long } }Den här koden kompileras nu, men körningen
X<int>.F(7)utlöser sedan ett undantag vid körning, eftersom en rutaintinte kan konverteras direkt till enlong.slutexempel
10.3.9 Användardefinierade explicita konverteringar
En användardefinierad explicit konvertering består av en valfri explicit standardkonvertering följt av körning av en användardefinierad implicit eller explicit konverteringsoperator följt av en annan valfri explicit standardkonvertering. De exakta reglerna för utvärdering av användardefinierade explicita konverteringar beskrivs i §10.5.5.
10.4 Standardkonverteringar
10.4.1 Allmänt
Standardkonverteringarna är de fördefinierade konverteringar som kan ske som en del av en användardefinierad konvertering.
10.4.2 Implicita standardkonverteringar
Följande implicita konverteringar klassificeras som implicita standardkonverteringar:
- Identitetskonverteringar (§10.2.2)
- Implicita numeriska konverteringar (§10.2.3)
- Implicita nullbara konverteringar (§10.2.6)
- Nullliterala konverteringar (§10.2.7)
- Implicita referenskonverteringar (§10.2.8)
- Boxningskonverteringar (§10.2.9)
- Implicita konverteringar av konstanta uttryck (§10.2.11)
- Implicita konverteringar med typparametrar (§10.2.12)
Implicita standardkonverteringar exkluderar specifikt användardefinierade implicita konverteringar.
10.4.3 Explicita standardkonverteringar
De explicita standardkonverteringarna är alla implicita standardkonverteringar plus delmängden av de explicita konverteringar för vilka det finns en implicit omvänd standardkonvertering.
Obs! Om det med andra ord finns en implicit standardkonvertering från en typ
Atill en typB, så finns det en explicit standardkonvertering från typAtill typBoch från typBtill typA. slutkommentar
10.5 Användardefinierade konverteringar
10.5.1 Allmänt
Med C# kan de fördefinierade implicita och explicita konverteringarna utökas med användardefinierade konverteringar. Användardefinierade konverteringar introduceras genom att konverteringsoperatorer (§15.10.4) deklareras i klass- och structtyper.
10.5.2 Tillåtna användardefinierade konverteringar
C# tillåter endast att vissa användardefinierade konverteringar deklareras. I synnerhet går det inte att omdefiniera en redan befintlig implicit eller explicit konvertering.
För en viss källtyp S och måltyp T, om S eller T är nullbara värdetyper, låter S₀ och T₀ refererar du till deras underliggande typer, i annat fall S₀ och T₀ är lika S med respektive T . En klass eller struct tillåts deklarera en konvertering från en källtyp S till en måltyp T endast om allt av följande är sant:
- 
              S₀ochT₀är olika typer.
- Antingen S₀ellerT₀är den klass- eller structtyp där operatordeklarationen äger rum.
- Varken eller S₀T₀är en interface_type.
- Förutom användardefinierade konverteringar finns det ingen konvertering från StillTeller frånTtillS.
De begränsningar som gäller för användardefinierade konverteringar anges i §15.10.4.
10.5.3 Utvärdering av användardefinierade konverteringar
En användardefinierad konvertering konverterar ett källuttryck, som kan ha en källtyp, till en annan typ som kallas måltyp. Utvärdering av ett användardefinierat konverteringscenter för att hitta den mest specifika användardefinierade konverteringsoperatorn för källuttrycket och måltypen. Den här bestämningen är uppdelad i flera steg:
- Hitta den uppsättning klasser och structs som användardefinierade konverteringsoperatorer kommer att övervägas från. Den här uppsättningen består av källtypen och dess basklasser, om källtypen finns, tillsammans med måltypen och dess basklasser. För detta ändamål förutsätts det att endast klasser och structs kan deklarera användardefinierade operatorer och att icke-klasstyper inte har några basklasser. Om antingen käll- eller måltypen är en nullable-value-type används deras underliggande typ i stället.
- Från den uppsättningen av typer avgör du vilka användardefinierade och hävda konverteringsoperatorer som är tillämpliga. För att en konverteringsoperatör ska vara tillämplig ska det vara möjligt att utföra en standardkonvertering (§10.4) från källuttrycket till operandtypen för operatören, och det ska vara möjligt att utföra en standardkonvertering från operatörens resultattyp till måltypen.
- Från uppsättningen med tillämpliga användardefinierade operatorer avgör du vilken operator som är tydligast den mest specifika. I allmänna termer är den mest specifika operatorn operatorn vars operandtyp är "närmast" källuttrycket och vars resultattyp är "närmast" måltypen. Användardefinierade konverteringsoperatorer föredras framför hävda konverteringsoperatorer. De exakta reglerna för att upprätta den mest specifika användardefinierade konverteringsoperatorn definieras i följande underfunktioner.
När en mest specifik användardefinierad konverteringsoperator har identifierats innebär den faktiska körningen av den användardefinierade konverteringen upp till tre steg:
- Om det behövs utför du först en standardkonvertering från källuttrycket till operandtypen för den användardefinierade eller hävda konverteringsoperatorn.
- Anropa sedan den användardefinierade eller hävda konverteringsoperatorn för att utföra konverteringen.
- Om det behövs utför du slutligen en standardkonvertering från resultattypen för den användardefinierade konverteringsoperatorn till måltypen.
Utvärdering av en användardefinierad konvertering omfattar aldrig mer än en användardefinierad eller hävd konverteringsoperator. Med andra ord kommer en konvertering från typ S till typ T aldrig först att köra en användardefinierad konvertering från S till X och sedan köra en användardefinierad konvertering från X till T.
- Exakta definitioner av utvärdering av användardefinierade implicita eller explicita konverteringar anges i följande underkliender. Definitionerna använder följande termer:
- Om en implicit standardkonvertering (§10.4.2) finns från en typ Atill en typB, och om varkenAellerBär interface_types, sägsAomfattas avB, ochBsägs omfattaA.
- Om det finns en implicit standardkonvertering (§10.4.2) från ett uttryck Etill en typB, och om varkenBeller typen avE(om den har en) är interface_types, sägsEvara omfattad avB, och sägsBomfattaE.
- Den mest omfattande typen i en uppsättning typer är den typ som omfattar alla andra typer i uppsättningen. Om ingen enskild typ omfattar alla andra typer har uppsättningen ingen mest omfattande typ. I mer intuitiva termer är den mest omfattande typen den "största" typen i uppsättningen – den typ som var och en av de andra typerna implicit kan konverteras till.
- Den mest omfattande typen i en uppsättning typer är den typ som omfattas av alla andra typer i uppsättningen. Om ingen enskild typ omfattas av alla andra typer har uppsättningen ingen mest omfattande typ. I mer intuitiva termer är den mest omfattande typen den "minsta" typen i uppsättningen – den typ som implicit kan konverteras till var och en av de andra typerna.
10.5.4 Användardefinierade implicita konverteringar
En användardefinierad implicit konvertering från ett uttryck E till en typ T bearbetas på följande sätt:
- Fastställa typerna - S,- S₀och- T₀.- Om Ehar en typ, låt varaSden typen.
- Om SellerTär nullbara värdetyper, låtSᵢochTᵢvara deras underliggande typer, annars låtSᵢochTᵢvaraSochT, respektive.
- Om SᵢellerTᵢär typparametrar, låtS₀ochT₀vara deras effektiva basklasser, annars låtS₀ochT₀varaSₓochTᵢ, respektive.
 
- Om 
- Leta reda på vilken uppsättning typer, - D, som användardefinierade konverteringsoperatorer ska övervägas från. Den här uppsättningen består av- S₀(om- S₀finns och är en klass eller struct), basklasserna- S₀för (om- S₀finns och är en klass) och- T₀(om- T₀är en klass eller struct). En typ läggs bara till i uppsättningen- Dom en identitetskonvertering till en annan typ som redan ingår i uppsättningen inte finns.
- Hitta uppsättningen med tillämpliga användardefinierade och hävda konverteringsoperatorer, - U. Den här uppsättningen består av de användardefinierade och lyfte implicita konverteringsoperatorerna som deklarerats av klasserna eller structarna i- Dsom konverterar från en typ som omfattar- Etill en typ som omfattas av- T. Om- Uär tom är konverteringen odefinierad och ett kompileringsfel inträffar.- Om Sfinns och någon av operatorerna iUkonvertera frånSärSₓ.S
- Annars Sₓär den mest omfattande typen i den kombinerade uppsättningen av källtyper för operatorerna iU. Om exakt en mest omfattande typ inte kan hittas är konverteringen tvetydig och ett kompileringsfel inträffar.
 
- Om 
- Hitta den mest specifika måltypen, - Tₓ, för operatorerna i- U:- Om någon av operatorerna konverteras UtillTärTₓ.T
- Annars Tₓär den mest omfattande typen i den kombinerade uppsättningen av måltyper för operatorerna iU. Om exakt en mest omfattande typ inte kan hittas är konverteringen tvetydig och ett kompileringsfel inträffar.
 
- Om någon av operatorerna konverteras 
- Hitta den mest specifika konverteringsoperatorn: - Om Uinnehåller exakt en användardefinierad konverteringsoperator som konverterar frånSₓtillTₓär detta den mest specifika konverteringsoperatorn.
- Om Uinnehåller exakt en hävd konverteringsoperator som konverterar frånSₓtillTₓär detta annars den mest specifika konverteringsoperatorn.
- Annars är konverteringen tvetydig och ett kompileringsfel inträffar.
 
- Om 
- Tillämpa slutligen konverteringen: - Om E inte redan har typen Sₓutförs en implicit standardkonvertering frånEtillSₓ.
- Den mest specifika konverteringsoperatorn anropas för att konvertera från SₓtillTₓ.
- Om TₓinteTutförs en implicit standardkonvertering frånTₓtillT.
 
- Om E inte redan har typen 
Det finns en användardefinierad implicit konvertering från en typ S till en typ T om det finns en användardefinierad implicit konvertering från en variabel av typen S till T.
10.5.5 Användardefinierade explicita konverteringar
En användardefinierad explicit konvertering från ett uttryck E till en typ T bearbetas på följande sätt:
- Fastställa typerna S,S₀ochT₀.- Om Ehar en typ, låt varaSden typen.
- Om SellerTär nullbara värdetyper, låtSᵢochTᵢvara deras underliggande typer, annars låtSᵢochTᵢvaraSochT, respektive.
- Om SᵢellerTᵢär typparametrar, låtS₀ochT₀vara deras effektiva basklasser, annars låtS₀ochT₀varaSᵢochTᵢ, respektive.
 
- Om 
- Leta reda på vilken uppsättning typer, D, som användardefinierade konverteringsoperatorer ska övervägas från. Den här uppsättningen består av (omS₀finns och är en klass eller struct), basklassernaS₀för (omS₀finns och är en klass),S₀(omT₀är en klass eller struct) och basklassernaT₀för (omT₀är enT₀klass). En typ läggs bara till i uppsättningenDom en identitetskonvertering till en annan typ som redan ingår i uppsättningen inte finns.
- Hitta uppsättningen med tillämpliga användardefinierade och hävda konverteringsoperatorer, U. Den här uppsättningen består av de användardefinierade och lyfta implicita eller explicita konverteringsoperatorerna som deklarerats av klasserna eller structarna iDsom konverterar från en typ som omfattarEeller omfattas avS(om den finns) till en typ som omfattar eller omfattas avT. OmUär tom är konverteringen odefinierad och ett kompileringsfel inträffar.
- Hitta den mest specifika källtypen, Sₓ, för operatorerna iU:- Om S finns och någon av operatorerna i Ukonvertera frånSärSₓ.S
- Om någon av operatorerna i Ukonverterar från typer som omfattarEär annarsSₓden mest omfattande typen i den kombinerade uppsättningen av källtyper för dessa operatorer. Om ingen mest omfattande typ kan hittas är konverteringen tvetydig och ett kompileringsfel inträffar.
- Annars Sₓär den mest omfattande typen i den kombinerade uppsättningen av källtyper för operatorerna iU. Om exakt en mest omfattande typ inte kan hittas är konverteringen tvetydig och ett kompileringsfel inträffar.
 
- Om S finns och någon av operatorerna i 
- Hitta den mest specifika måltypen, Tₓ, för operatorerna iU:- Om någon av operatorerna konverteras UtillTärTₓ.T
- Om någon av operatorerna i Ukonverterar till typer som omfattas avTär annarsTₓden mest omfattande typen i den kombinerade uppsättningen av måltyper för dessa operatorer. Om exakt en mest omfattande typ inte kan hittas är konverteringen tvetydig och ett kompileringsfel inträffar.
- Annars Tₓär den mest omfattande typen i den kombinerade uppsättningen av måltyper för operatorerna iU. Om ingen mest omfattande typ kan hittas är konverteringen tvetydig och ett kompileringsfel inträffar.
 
- Om någon av operatorerna konverteras 
- Hitta den mest specifika konverteringsoperatorn: - Om U innehåller exakt en användardefinierad konverteringsoperator som konverterar från SₓtillTₓär detta den mest specifika konverteringsoperatorn.
- Om Uinnehåller exakt en hävd konverteringsoperator som konverterar frånSₓtillTₓär detta annars den mest specifika konverteringsoperatorn.
- Annars är konverteringen tvetydig och ett kompileringsfel inträffar.
 
- Om U innehåller exakt en användardefinierad konverteringsoperator som konverterar från 
- Tillämpa slutligen konverteringen: - Om Einte redan har typenSₓutförs en explicit standardkonvertering från E tillSₓ.
- Den mest specifika användardefinierade konverteringsoperatorn anropas för att konvertera från SₓtillTₓ.
- Om TₓinteTutförs en explicit standardkonvertering frånTₓtillT.
 
- Om 
Det finns en användardefinierad explicit konvertering från en typ S till en typ T om det finns en användardefinierad explicit konvertering från en variabel av typen S till T.
10.6 Konverteringar som omfattar nullbara typer
10.6.1 Nullable Konverteringar
              
              Med null-konverteringar kan fördefinierade konverteringar som körs på icke-nullbara värdetyper också användas med nullbara former av dessa typer. För var och en av de fördefinierade implicita eller explicita konverteringarna som konverterar från en värdetyp S som inte kan nollställas till en värdetyp T som inte kan nulleras (§10.2.2, §10.2.3, §10.2.4, §10.2.11, §10.3.2 och §10.3.3) finns följande nullbara konverteringar:
- En implicit eller explicit konvertering från S?tillT?
- En implicit eller explicit konvertering från StillT?
- En explicit konvertering från S?tillT.
En nullbar konvertering klassificeras i sig som en implicit eller explicit konvertering.
Vissa nullbara konverteringar klassificeras som standardkonverteringar och kan ske som en del av en användardefinierad konvertering. Mer specifikt klassificeras alla implicita nullbara konverteringar som implicita standardkonverteringar (§10.4.2) och de explicita nullbara konverteringar som uppfyller kraven i §10.4.3 klassificeras som explicita standardkonverteringar.
Utvärdering av en nullbar konvertering baserat på en underliggande konvertering från S till T intäkter enligt följande:
- Om den nullbara konverteringen är från S?tillT?:- Om källvärdet är null (HasValueegenskapen ärfalse), är resultatet nullvärdet av typenT?.
- I annat fall utvärderas konverteringen som en avskrivning från S?tillS, följt av den underliggande konverteringen frånStillT, följt av en omslutning frånTtillT?.
 
- Om källvärdet är null (
- Om den nullbara konverteringen är från StillT?utvärderas konverteringen som den underliggande konverteringen frånStillTföljt av en omslutning frånTtillT?.
- Om den nullbara konverteringen är från S?tillTutvärderas konverteringen som en avskrivning frånS?tillSföljt av den underliggande konverteringen frånStillT.
10.6.2 Hävda konverteringar
Med tanke på en användardefinierad konverteringsoperator som konverterar från en värdetyp S som inte kan nollställas till en värdetyp Tsom inte är null finns det en hävd konverteringsoperator som konverterar från S? till T?. Den här hävda konverteringsoperatorn utför en avskrivning från S? till S följt av den användardefinierade konverteringen från S till T följt av en omslutning från T till T?, förutom att ett nullvärde S? konverteras direkt till ett nullvärde T?. En hävd konverteringsoperator har samma implicita eller explicita klassificering som den underliggande användardefinierade konverteringsoperatorn.
10.7 Anonyma funktionskonverteringar
10.7.1 Allmänt
En anonymous_method_expression eller lambda_expression klassificeras som en anonym funktion (§12.20). Uttrycket har ingen typ, men kan implicit konverteras till en kompatibel ombudstyp. Vissa lambda-uttryck kan också implicit konverteras till en kompatibel uttrycksträdstyp.
Mer specifikt är en anonym funktion F kompatibel med en delegerad typ D som tillhandahålls:
- Om Finnehåller en anonymous_function_signature ochDharFsamma antal parametrar.
- Om Finte innehåller en anonymous_function_signature kan detDfinnas noll eller fler parametrar av någon typ, så länge ingen parameterDär en utdataparameter.
- Om Fhar en uttryckligen angiven parameterlista har varje parameter iDsamma modifierare som motsvarande parameter iFoch en identitetskonvertering finns mellan motsvarande parameter iF.
- Om Fhar en implicit typad parameterlistaDhar du inga referens- eller utdataparametrar.
- Om brödtexten Fär ett uttryck och antingenDhar returtypen void ellerFär asynkron ochDhar en«TaskType»returtyp (§15.14.1), så när varje parameter avFfår typen motsvarande parametern iD, är brödtextenFett giltigt uttryck (på det sättet §12) som skulle tillåtas som en statement_expression (§13.7).
- Om brödtexten Fi är ett block och antingenDhar en ogiltig returtyp ellerFär asynkron ochDhar en«TaskType»returtyp , är brödtextenFiDett giltigt block (w.r.tF) där ingen instruktion anger ett uttryck när varje parameterreturnanges.
- Om kroppdelen Fär ett uttryck, och antingenFär icke-asynkron ochDhar en returtyp som inte ärvoidT, ellerFär asynkron ochDhar en«TaskType»<T>returtyp (§15.14.1), då när varje parameter iFges typen av den motsvarande parametern iD, är kroppenFett giltigt uttryck (enl. §12), som implicit kan konverteras tillT.
- Om brödtexten Fi är ett block och antingenFär icke-asynkron ochDhar en icke-void returtypT, ellerFär asynkron ochDhar en«TaskType»<T>returtyp, är brödtextenFiDett giltigt instruktionsblock (w.r.tF) med en icke-nåbar slutpunkt där varje retursats anger ett uttryck som implicit kan konverteras tillT.
Exempel: Följande exempel illustrerar dessa regler:
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"; };slutexempel
Exempel: Exemplen som följer använder en allmän ombudstyp
Func<A,R>som representerar en funktion som tar ett argument av typenAoch returnerar ett värde av typenR:delegate R Func<A,R>(A arg);I tilldelningarna
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; // Okparametern och returtyperna för varje anonym funktion bestäms utifrån vilken typ av variabel som den anonyma funktionen tilldelas till.
Den första tilldelningen konverterar den anonyma funktionen till ombudstypen
Func<int,int>eftersom närxär given typintx + 1är ett giltigt uttryck som implicit kan konverteras till typenint.På samma sätt konverterar den andra tilldelningen den anonyma funktionen till delegattypen Func int,double< eftersom resultatet av (av > typen
x + 1) implicit kan konverteras till typenint.doubleDen tredje tilldelningen är dock ett kompileringsfel eftersom resultatet av (av
xtypen ) inte implicit kan konverteras till typendoublenärx + 1den är given typdoubleint.Den fjärde tilldelningen konverterar den anonyma asynkrona funktionen till delegattypen
Func<int, Task<int>>eftersom resultatet av (avx + 1typenint) implicit konverteras till den effektiva returtypenintför async lambda, som har en returtypTask<int>.slutexempel
Ett lambda-uttryck F är kompatibelt med en uttrycksträdstyp Expression<D> om F det är kompatibelt med ombudstypen D. Detta gäller inte för anonyma metoder, bara lambda-uttryck.
Anonyma funktioner kan påverka överbelastningsmatchning och delta i typinferens. Mer information finns i §12.6 .
10.7.2 Utvärdering av anonyma funktionskonverteringar till ombudstyper
Konvertering av en anonym funktion till en delegattyp skapar en delegatinstans som refererar till den anonyma funktionen och den (eventuellt tomma) uppsättningen av insamlade yttre variabler som är aktiva vid tidpunkten för utvärderingen. När ombudet anropas körs brödtexten för den anonyma funktionen. Koden i brödtexten körs med hjälp av den uppsättning insamlade yttre variabler som refereras av ombudet. En delegate_creation_expression (§12.8.17.5) kan användas som en alternativ syntax för att konvertera en anonym metod till en ombudstyp.
Anropslistan för ett ombud som skapats från en anonym funktion innehåller en enda post. Ombudets exakta målobjekt och målmetod är ospecificerade. I synnerhet är det ospecificerat om målobjektet för ombudet är null, this värdet för den omslutande funktionsmedlemmen eller något annat objekt.
Konverteringar av semantiskt identiska anonyma funktioner med samma (eventuellt tomma) uppsättning insamlade yttre variabelinstanser till samma ombudstyper tillåts (men krävs inte) för att returnera samma delegatinstans. Termen semantiskt identisk används här för att innebära att körningen av anonyma funktioner i samtliga fall ger samma effekter med samma argument. Den här regeln tillåter att kod som följande optimeras.
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));
        ...
    }
}
Eftersom de två anonyma funktionsdelegaterna har samma (tomma) uppsättning insamlade yttre variabler, och eftersom de anonyma funktionerna är semantiskt identiska, tillåts en kompilator att låta ombuden referera till samma målmetod. En kompilator kan faktiskt returnera samma delegatinstans från båda anonyma funktionsuttrycken.
10.7.3 Utvärdering av lambda-uttryckskonverteringar till uttrycksträdstyper
Konvertering av ett lambda-uttryck till en uttrycksträdstyp skapar ett uttrycksträd (§8.6). Mer exakt ger utvärderingen av lambda-uttryckskonverteringen en objektstruktur som representerar själva lambda-uttryckets struktur.
Alla lambda-uttryck kan inte konverteras till uttrycksträdstyper. Konverteringen till en kompatibel delegattyp finns alltid, men den kan misslyckas vid kompileringstid av implementeringsdefinierade orsaker.
Obs! Vanliga orsaker till att ett lambda-uttryck inte kan konverteras till en uttrycksträdstyp är:
- Den har en blocktext
- Den har modifieraren
async- Den innehåller en tilldelningsoperator
- Den innehåller en utdata- eller referensparameter
- Den innehåller ett dynamiskt bundet uttryck
slutkommentar
10.8 Gruppkonverteringar för metod
En implicit konvertering finns från en metodgrupp (§12.2) till en kompatibel delegattyp (§21.4). Om D är en ombudstyp och E är ett uttryck som klassificeras som en metodgrupp är det D kompatibelt med E om och endast om E innehåller minst en metod som är tillämplig i sin normala form (§12.6.4.2) på alla argumentlistor (§12.6.2) med typer och modifierare som matchar parametertyperna och modifierarna Di , enligt beskrivningen i följande.
Kompileringstidsapplikationen för konverteringen från en metodgrupp E till en ombudstyp D beskrivs i följande.
- En enskild metod Mväljs som motsvarar ett metodanrop (§12.8.10.2) i formuläretE(A), med följande ändringar:- Argumentlistan Aär en lista över uttryck, var och en klassificerad som en variabel och med typen och modifieraren (in,out, ellerref) för motsvarande parameter i parameter_list avD, förutom parametrar av typendynamic, där motsvarande uttryck har typenobjecti stället fördynamic.
- De kandidatmetoder som beaktas är endast de metoder som är tillämpliga i sin normala form och inte utelämnar några valfria parametrar (§12.6.4.2). Därför ignoreras kandidatmetoder om de endast är tillämpliga i sin utökade form, eller om en eller flera av deras valfria parametrar inte har någon motsvarande parameter i D.
 
- Argumentlistan 
- En konvertering anses existera om algoritmen i §12.8.10.2 producerar en enda bästa metod Msom är kompatibel (§21.4) medD.
- Om den valda metoden Mär en instansmetod avgör instansuttrycket som är associerat medEombudets målobjekt.
- Om den valda metoden Mär en tilläggsmetod som anges med hjälp av en medlemsåtkomst i ett instansuttryck, avgör instansuttrycket ombudets målobjekt.
- Resultatet av konverteringen är ett värde av typen D, nämligen ett ombud som refererar till den valda metoden och målobjektet.
Exempel: Följande visar metodgruppkonverteringar:
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 } }Tilldelningen konverterar
d1implicit metodgruppenFtill ett värde av typenD1.Tilldelningen som
d2visar hur det är möjligt att skapa ett ombud till en metod som har mindre härledda (kontravarianta) parametertyper och en mer härledd (covariant) returtyp.Tilldelningen som
d3visar hur ingen konvertering finns om metoden inte är tillämplig.Tilldelningen som
d4visar hur metoden måste vara tillämplig i sin normala form.Tilldelningen som
d5visar hur parameter- och returtyper för ombudet och metoden endast tillåts skilja sig åt för referenstyper.slutexempel
Precis som med alla andra implicita och explicita konverteringar kan cast-operatorn användas för att explicit utföra en viss konvertering.
Exempel: Därför är exemplet
object obj = new EventHandler(myDialog.OkClick);kan skrivas i stället
object obj = (EventHandler)myDialog.OkClick;slutexempel
En metodgruppkonvertering kan referera till en allmän metod, antingen genom att uttryckligen ange typargument inom Eeller via typinferens (§12.6.3). Om typinferens används används parametertyperna för ombudet som argumenttyper i slutsatsdragningsprocessen. Returtypen för ombudet används inte för slutsatsdragning. Oavsett om typargumenten anges eller härleds ingår de i metodgruppens konverteringsprocess. det här är de typargument som används för att anropa målmetoden när det resulterande ombudet anropas.
Exempel:
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 } }slutexempel
Metodgrupper kan påverka överbelastningsmatchning och delta i typinferens. Mer information finns i §12.6 .
Körningsutvärderingen av en metodgruppkonvertering fortsätter på följande sätt:
- Om den metod som valts vid kompileringstid är en instansmetod, eller om det är en tilläggsmetod som används som en instansmetod, bestäms målobjektet för ombudet från instansuttrycket som är associerat med E:- Instansuttrycket utvärderas. Om den här utvärderingen orsakar ett undantag körs inga ytterligare steg.
- Om instansuttrycket är av en reference_type blir värdet som beräknas av instansuttrycket målobjektet. Om den valda metoden är en instansmetod och målobjektet är nullgenereras enSystem.NullReferenceExceptionoch inga ytterligare steg körs.
- Om instansuttrycket är av en value_type utförs en boxningsåtgärd (§10.2.9) för att konvertera värdet till ett objekt, och det här objektet blir målobjektet.
 
- Annars är den valda metoden en del av ett statiskt metodanrop och målobjektet för ombudet är null.
- En delegatinstans av ombudstyp Dhämtas med en referens till metoden som fastställdes vid kompileringstiden och en referens till målobjektet som beräknades ovan enligt följande:- Konverteringen tillåts (men krävs inte) för att använda en befintlig ombudsinstans som redan innehåller dessa referenser.
- Om en befintlig instans inte återanvänds skapas en ny (§21.5). Om det inte finns tillräckligt med minne tillgängligt för att allokera den nya instansen genereras en System.OutOfMemoryException. Annars initieras instansen med de angivna referenserna.
 
ECMA C# draft specification