Dela via


De markerade och omarkerade instruktionerna (C#-referens)

Instruktionen checked och unchecked anger överflödeskontrollkontexten för aritmetiska åtgärder av typen integraltyp och konverteringar. Standarduttalandet är unchecked. När heltalsaritmiskt spill inträffar definierar överflödeskontrollkontexten vad som händer. I en kontrollerad kontext kastas en System.OverflowException; om ett 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 övergår addition 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.
}

Anteckning

Ö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 kan användardefinierade kontrollerade operatorer kanske inte utlösa ett undantag i ett kontrollerat sammanhang.

Mer information finns i avsnitten Aritmetiskt överflöde 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.
}

Satserna checked och operatorerna unchecked påverkar bara överflödeskontrollkontexten för de operationer 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 det föregående exemplet visar det första anropet av den Multiply lokala funktionen att instruktionen checked inte påverkar överflödeskontrollkontexten inom funktionen Multiply eftersom ingen undantagskastning sker. Vid det andra anropet av funktionen Multiply utvärderas uttrycket som beräknar det andra argumentet för funktionen i en kontrollerad kontext, vilket resulterar i ett undantag eftersom det ligger inom blocket för checked-instruktionen.

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, doubleoch 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, doubleoch Half har förnuftiga mättnadsvärden för PositiveInfinity och NegativeInfinity, så att du kan identifiera spill i en unchecked kontext. För decimalfinns 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 checked en unchecked kontext.

Åtgärder som påverkas av överflödeskontrollkontexten

Kontexten för spillkontroll påverkar följande åtgärder:

Standardkontext för överflödskontroll

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:

Se även