De markerade och omarkerade instruktionerna (C#-referens)
Instruktionen checked
och unchecked
anger överflödeskontrollkontexten för aritmetiska åtgärder av typen integraltyp och konverteringar. När heltalsaritmiskt spill inträffar definierar överflödeskontrollkontexten vad som händer. I en markerad kontext utlöses en System.OverflowException . Om spill inträffar i ett konstant uttryck uppstår ett kompileringsfel. I en omarkerad kontext trunkeras åtgärdsresultatet genom att alla bitar i hög ordning som inte får plats i måltypen ignoreras. Till exempel omsluts tillägg från det maximala värdet till minimivärdet. I följande exempel visas samma åtgärd i både en markerad och omarkerad kontext:
uint a = uint.MaxValue;
unchecked
{
Console.WriteLine(a + 3); // output: 2
}
try
{
checked
{
Console.WriteLine(a + 3);
}
}
catch (OverflowException e)
{
Console.WriteLine(e.Message); // output: Arithmetic operation resulted in an overflow.
}
Kommentar
Överflödets beteende för användardefinierade operatorer och konverteringar kan skilja sig från det som beskrivs i föregående stycke. I synnerhet kanske användardefinierade kontrollerade operatorer inte utlöser ett undantag i en kontrollerad kontext.
Mer information finns i avsnittet Aritmetiska spill och division med noll och användardefinierade kontrollerade operatorer i artikeln Aritmetiska operatorer .
Om du vill ange kontexten för spillkontroll för ett uttryck kan du också använda operatorerna checked
och unchecked
, som följande exempel visar:
double a = double.MaxValue;
int b = unchecked((int)a);
Console.WriteLine(b); // output: -2147483648
try
{
b = checked((int)a);
}
catch (OverflowException e)
{
Console.WriteLine(e.Message); // output: Arithmetic operation resulted in an overflow.
}
Operatorerna checked
och unchecked
och påverkar bara överflödeskontrollkontexten för de åtgärder som är textuellt inuti instruktionsblocket eller operatorns parenteser, som följande exempel visar:
int Multiply(int a, int b) => a * b;
int factor = 2;
try
{
checked
{
Console.WriteLine(Multiply(factor, int.MaxValue)); // output: -2
}
}
catch (OverflowException e)
{
Console.WriteLine(e.Message);
}
try
{
checked
{
Console.WriteLine(Multiply(factor, factor * int.MaxValue));
}
}
catch (OverflowException e)
{
Console.WriteLine(e.Message); // output: Arithmetic operation resulted in an overflow.
}
I föregående exempel visar den första anropet av den Multiply
lokala funktionen att instruktionen checked
inte påverkar överflödeskontrollkontexten Multiply
i funktionen eftersom inget undantag utlöses. Vid funktionens andra anrop Multiply
utvärderas uttrycket som beräknar funktionens andra argument i en kontrollerad kontext och resulterar i ett undantag eftersom det är textmässigt inuti -blocket i -instruktionen checked
.
Beteendet för checked
och unchecked
beror på typen och åtgärden. Även för heltal genererar åtgärder som unchecked(x / 0)
alltid eftersom det inte finns något vettigt beteende. Kontrollera beteendet för typen och åtgärden för att förstå hur nyckelorden checked
och unchecked
påverkar koden.
Numeriska typer och överflödeskontrollkontext
Nyckelorden checked
och unchecked
gäller främst för integraltyper där det finns ett förnuftigt spillbeteende. Omslutningsbeteendet där T.MaxValue + 1
blir T.MinValue
är förnuftigt i en tvåas komplementvärde. Det representerade värdet är inte korrekt eftersom det inte får plats i lagringen för typen. Därför är bitarna representativa för de lägre n-bitar av det fullständiga resultatet.
För typer som decimal
, float
, double
och Half
som representerar ett mer komplext värde eller ett komplementvärde är omslutning inte förnuftigt. Det kan inte användas för att beräkna större eller mer exakta resultat, så unchecked
det är inte fördelaktigt.
float
, double
och Half
har förnuftiga mättnadsvärden för PositiveInfinity
och NegativeInfinity
, så att du kan identifiera spill i en unchecked
kontext. För decimal
finns inga sådana gränser, och mättnad vid MaxValue
kan leda till fel eller förvirring. Åtgärder som använder decimal
genererar både en kontext och unchecked
en checked
kontext.
Åtgärder som påverkas av överflödeskontrollkontexten
Kontexten för spillkontroll påverkar följande åtgärder:
Följande inbyggda aritmetiska operatorer: unary
++
,--
,-
och binary+
,-
,*
och/
operatorer, när deras operander är av en integrerad typ (dvs. antingen integral numerisk eller teckentyp ) eller en uppräkningstyp .Explicita numeriska konverteringar mellan integraltyper eller från
float
ellerdouble
till en integrerad typ.Kommentar
När du konverterar ett
decimal
värde till en integrerad typ och resultatet ligger utanför måltypens intervall genereras alltid ett OverflowException värde, oavsett kontexten för spillkontroll.Från och med C# 11, användardefinierade kontrollerade operatorer och konverteringar. Mer information finns i avsnittet Användardefinierade kontrollerade operatorer i artikeln Aritmetiska operatorer .
Standardkontext för spillkontroll
Om du inte anger kontexten för spillkontroll definierar värdet för kompileringsalternativet CheckForOverflowUnderflow standardkontexten för icke-stantuttryck. Som standard är värdet för det alternativet oetat och aritmetiska åtgärder av typen integraltyp och konverteringar körs i en omarkerad kontext.
Konstanta uttryck utvärderas som standard i en kontrollerad kontext och spill orsakar ett kompileringsfel. Du kan uttryckligen ange en omarkerad kontext för ett konstant uttryck med instruktionen unchecked
eller operatorn.
Språkspecifikation för C#
Mer information finns i följande avsnitt i C#-språkspecifikationen:
- De markerade och omarkerade uttrycken
- De markerade och avmarkerade operatorerna
- Användardefinierade markerade och avmarkerade operatorer – C# 11