Udostępnij za pośrednictwem


Zaznaczone i niezaznaczone instrukcje (odwołanie w C#)

Instrukcje checked i unchecked określają kontekst sprawdzania przepełnienia dla operacji arytmetycznych i konwersji typu całkowitego. Gdy występuje przepełnienie arytmetyczne liczb całkowitych, kontekst sprawdzania przepełnienia definiuje, co się dzieje. W zaznaczonym kontekście System.OverflowException jest zgłaszany element . Jeśli przepełnienie występuje w wyrażeniu stałym, wystąpi błąd czasu kompilacji. W niezaznaczonym kontekście wynik operacji jest obcinany przez odrzucenie wszystkich bitów o wysokiej kolejności, które nie mieszczą się w typie docelowym. Na przykład dodanie zawija się z maksymalnej wartości do wartości minimalnej. W poniższym przykładzie pokazano tę samą operację zarówno w kontekście zaznaczonym, jak i niezaznaczonej:

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.
}

Uwaga

Zachowanie przepełnienia operatorów zdefiniowanych przez użytkownika i konwersji może różnić się od tego, który został opisany w poprzednim akapicie. W szczególności operatory sprawdzane przez użytkownika mogą nie zgłaszać wyjątku w zaznaczonym kontekście.

Aby uzyskać więcej informacji, zobacz sekcje Przepełnienie arytmetyczne i dzielenie według zera i Operatory sprawdzone zdefiniowane przez użytkownika w artykule Operatory arytmetyczne.

Aby określić kontekst sprawdzania przepełnienia dla wyrażenia, można również użyć checked operatorów i unchecked , jak pokazano w poniższym przykładzie:

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.
}

Instrukcje checked i unchecked i operatory mają wpływ tylko na kontekst sprawdzania przepełnienia dla tych operacji, które są tekstowo wewnątrz bloku instrukcji lub nawiasów operatora, jak pokazano w poniższym przykładzie:

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.
}

W poprzednim przykładzie pierwsze wywołanie Multiply funkcji lokalnej pokazuje, że checked instrukcja nie ma wpływu na kontekst sprawdzania przepełnienia w Multiply ramach funkcji, ponieważ nie jest zgłaszany żaden wyjątek. Podczas drugiego Multiply wywołania funkcji wyrażenie, które oblicza drugi argument funkcji, jest obliczane w kontekście sprawdzanym i powoduje wyjątek, ponieważ jest tekstowo wewnątrz bloku checked instrukcji .

Zachowanie i checked unchecked zależy od typu i operacji. Nawet w przypadku liczb całkowitych operacje takie jak unchecked(x / 0) zawsze zgłaszane, ponieważ nie ma rozsądnego zachowania. Sprawdź zachowanie typu i operacji, aby zrozumieć, jak słowa checked kluczowe i unchecked wpływają na kod.

Typy liczbowe i kontekst sprawdzania przepełnienia

Słowa checked kluczowe i unchecked dotyczą głównie typów całkowitych, w których występuje rozsądne zachowanie przepełnienia. Zachowanie zawijania, w którym T.MaxValue + 1 staje się T.MinValue rozsądne w wartości uzupełniającej dwóch. Reprezentowana wartość nie jest poprawna , ponieważ nie może zmieścić się w magazynie dla typu. W związku z tym bity są reprezentatywne dla niższych n-bitów pełnego wyniku.

W przypadku typów, takich jak decimal, float, doublei Half reprezentujących bardziej złożoną wartość lub wartość uzupełniającą, zawijanie nie jest rozsądne. Nie można jej używać do obliczania większych lub bardziej dokładnych wyników, więc unchecked nie jest korzystne.

float, doublei Half mają rozsądne wartości saturujące dla PositiveInfinity i NegativeInfinity, dzięki czemu można wykryć przepełnienie w unchecked kontekście. W przypadku decimalprogramu nie istnieją takie limity, a saturacja w MaxValue programie może prowadzić do błędów lub nieporozumień. Operacje używające decimal rzutu zarówno w kontekście, jak i checked unchecked .

Operacje, na które ma wpływ kontekst sprawdzania przepełnienia

Kontekst sprawdzania przepełnienia ma wpływ na następujące operacje:

Domyślny kontekst sprawdzania przepełnienia

Jeśli nie określisz kontekstu sprawdzania przepełnienia, wartość opcji kompilatora CheckForOverflowUnderflow definiuje domyślny kontekst dla wyrażeń niezdecydowanych. Domyślnie wartość tej opcji jest niezwiązana, a operacje arytmetyczne i konwersje typu całkowitego są wykonywane w nieznakowanym kontekście.

Wyrażenia stałe są domyślnie oceniane w zaznaczonym kontekście i przepełnienie powoduje błąd czasu kompilacji. Można jawnie określić nieznakowany kontekst dla wyrażenia stałego za pomocą instrukcji unchecked lub operatora.

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz następujące sekcje specyfikacji języka C#:

Zobacz też