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. 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, 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 unchecked en checked kontext.

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

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

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:

Se även