Freigeben über


Die geprüften und ungeprüften Anweisungen (C#-Referenz)

Mit den Anweisungen checked und unchecked wird der Überlaufprüfungskontext für arithmetische Operationen und Konvertierungen vom integralen Typ gesteuert. Die Standard-Anweisung lautet unchecked. Wenn ein arithmetischer Integerüberlauf auftritt, definiert der Überlaufprüfungskontext wie folgt, was geschieht. In einem überprüften Kontext wird eine System.OverflowException ausgelöst; tritt ein Überlauf in einem konstanten Ausdruck auf, so führt dies zu einem Kompilierzeitfehler. In einem nicht überprüften Kontext wird das Ergebnis der Operation gekürzt, indem alle höherwertigen Bits verworfen werden, die nicht in den Zieltyp passen. Zum Beispiel geht die Addition vom Maximalwert zum Minimalwert über. Das folgende Beispiel zeigt denselben Vorgang sowohl in einem "checked"- als auch in einem "unchecked"-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.
}

Hinweis

Das Überlaufverhalten von benutzerdefinierten Operatoren und Konvertierungen kann sich von der im vorherigen Absatz beschriebenen unterscheiden. Insbesondere lösen benutzerdefinierte checked-Operatoren möglicherweise keine Ausnahme in einem checked-Kontext aus.

Weitere Informationen finden Sie im Artikel Arithmetische Operatoren in den Abschnitten Arithmetischer Überlauf und Division durch Null und Benutzerdefinierte geprüfte Operatoren.

Um den Kontext der Überlaufüberprüfung für einen Ausdruck anzugeben, können Sie auch die Operatoren checked und unchecked verwenden, wie im folgenden Beispiel gezeigt:

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

Die checked- und unchecked-Anweisungen und -Operatoren beeinflussen nur den Kontext der Überlaufüberprüfung für jene Operationen, die sich inhaltlich innerhalb des Anweisungsblocks oder der Klammern des Operators befinden, wie im folgenden Beispiel gezeigt wird.

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

Im vorherigen Beispiel zeigt der erste Aufruf der lokalen Multiply-Funktion, dass sich die checked-Anweisung nicht auf den Kontext der Überlaufüberprüfung innerhalb der Multiply-Funktion auswirkt, da keine Ausnahme ausgelöst wird. Beim zweiten Aufruf der Multiply-Funktion wird der Ausdruck, der das zweite Argument der Funktion berechnet, in einem checked-Kontext ausgewertet und führt zu einer Ausnahme, da er sich textlich innerhalb des Blocks der checked-Anweisung befindet.

Das Verhalten von checked und unchecked hängt vom Typ und vom Vorgang ab. Selbst bei ganzen Zahlen führen Operationen wie unchecked(x / 0) immer zum Überlauf, weil es kein vernünftiges Verhalten gibt. Überprüfen Sie das Verhalten für den Typ und den Vorgang, um zu verstehen, wie sich die checked Und unchecked Schlüsselwörter auf Ihren Code auswirken.

Numerische Typen und Überlaufprüfungskontext

Die Schlüsselwörter checked und unchecked gelten in erster Linie für integrale Datentypen, wo ein sinnvolles Überlaufverhalten vorhanden ist. Das Wraparound-Verhalten, bei dem T.MaxValue + 1 zu T.MinValue wird, ist bei einem Zweierkomplement-Wert sinnvoll. Der dargestellte Wert ist nicht korrekt , da er nicht in den Speicher für den Typ passt. Daher sind die Bits repräsentativ für die unteren n-Bits des vollständigen Ergebnisses.

Bei Typen wie decimal, float, double und Half, die einen komplexeren Wert oder einen Einerkomplementwert darstellen, ist Wraparound nicht sinnvoll. Es kann nicht verwendet werden, um größere oder genauere Ergebnisse zu berechnen, daher unchecked ist es nicht vorteilhaft.

float, doubleund Half verfügen über vernünftige Sättigungswerte für PositiveInfinity und NegativeInfinity, damit Sie Überlauf in einem unchecked Kontext erkennen können. Für decimal gibt es keine solchen Grenzen, und die Sättigung bei MaxValue kann zu Fehlern oder Verwirrung führen. Operationen, die decimal verwenden, werfen sowohl in einem checked- als auch in einem unchecked-Kontext.

Vom Kontext der Überlaufüberprüfung betroffene Operationen

Der Kontext der Überlaufüberprüfung wirkt sich auf die folgenden Operationen aus:

Standardmäßiger Kontext der Überlaufüberprüfung

Wenn Sie den Überlaufüberprüfungskontext nicht angeben, definiert der Wert der CheckForOverflowUnderflow-Compileroption den Standardkontext für nicht zusammenhängende Ausdrücke. Standardmäßig ist der Wert dieser Option nicht festgelegt, und arithmetische Operationen des Integraltyps werden in einem unchecked-Kontext ausgeführt.

Konstantenausdrücke werden standardmäßig in einem überprüften Kontext ausgewertet, und Überlauf verursacht einen Kompilierzeitfehler. Sie können einen unchecked-Kontext für einen konstanten Ausdruck explizit mit unchecked-Anweisung oder -Operator angeben.

C#-Sprachspezifikation

Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:

Siehe auch