Die aktivierten und deaktivierten Anweisungen (C#-Referenz)
Mit den Anweisungen checked
und unchecked
wird der Überlaufprüfungskontext für arithmetische Operationen und Konvertierungen vom integralen Typ gesteuert. Wenn ein arithmetischer Integerüberlauf auftritt, definiert der Überlaufprüfungskontext wie folgt, was geschieht. In einem checked-Kontext wird eine System.OverflowException ausgelöst, wenn bei einem Überlauf in einem konstanten Ausdruck ein Kompilierzeitfehler auftritt. In einem unchecked-Kontext wird das Ergebnis der Operation gekürzt, indem alle höherwertigen Bits verworfen werden, die nicht in den Zieltyp passen. Das Hinzufügen wird beispielsweise von dem Maximalwert bis zum Minimalwert umbrochen. Das folgende Beispiel zeigt denselben Vorgang in einem checked- und 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 checked-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 wirken sich nur für Operationen, die sich textlich innerhalb des Anweisungsblocks oder der Klammern des Operators befinden, auf den Kontext der Überlaufüberprüfung für Operationen aus, wie im folgenden Beispiel gezeigt:
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 und checked
unchecked
hängt vom Typ und vom Vorgang ab. Auch für ganze Zahlen werden Vorgänge wie unchecked(x / 0)
immer ausgelöst, da kein vernünftiges Verhalten vorhanden ist. Ü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 Überlaufüberprüfungskontext
Die checked
Schlüsselwörter unchecked
gelten in erster Linie für integrale Typen, bei denen ein vernünftiges Überlaufverhalten vorhanden ist. Das Wraparound-Verhalten, bei dem T.MaxValue + 1
in einem Zwei-Ergänzungswert sinnvoll wird T.MinValue
. 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.
Für Typen wie decimal
, float
, double
und Half
die einen komplexeren Wert oder den Ergänzungswert eines betreffenden Darstellens 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
, double
und 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 , gibt decimal
es keine solchen Grenzen, und die Sättigung an MaxValue
kann zu Fehlern oder Verwirrung führen. Vorgänge, die decimal
ausgelöst werden, sowohl in einem als unchecked
auch in einem checked
Kontext.
Vom Kontext der Überlaufüberprüfung betroffene Operationen
Der Kontext der Überlaufüberprüfung wirkt sich auf die folgenden Operationen aus:
Die folgenden integrierten arithmetischen Operatoren: unäre
++
-,--
-,-
- und binäre+
-,-
-,*
- und/
-Operatoren, wenn ihre Operanden vom integralen Typ sind (d. h. entweder integraler numerischer Typ oder char-Typ ) oder enum-Typ.Explizite numerische Konvertierungen zwischen ganzzahligen Typen oder von
float
oderdouble
in einen integralen Typ.Hinweis
Wenn Sie einen
decimal
-Wert in einen integralen Typ konvertieren und das Ergebnis außerhalb des Bereichs des Zieltyps liegt, wird unabhängig vom Kontext der Überlaufüberprüfung immer eine OverflowException ausgelöst.Ab C# 11 werden benutzerdefinierte checked-Operatoren und -Konvertierungen durchgeführt. Weitere Informationen finden Sie im Abschnitt Benutzerdefinierte checked-Operatoren des Artikels Arithmetische Operatoren.
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 in einem überprüften Kontext standardmäßig ausgewertet, und überlauf verursacht einen Kompilierungszeitfehler. 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:
- The checked and unchecked statements (Geprüfte und nicht geprüfte Anweisungen)
- The checked and unchecked operators (Checked- und Unchecked-Operatoren)
- Benutzerdefinierte checked- und unchecked-Operatoren – C# 11