Uitzonderingen maken en genereren
Uitzonderingen worden gebruikt om aan te geven dat er een fout is opgetreden tijdens het uitvoeren van het programma. Uitzonderingsobjecten die een fout beschrijven, worden gemaakt en vervolgens gegenereerd met de throw
instructie of expressie. De runtime zoekt vervolgens naar de meest compatibele uitzonderingshandler.
Programmeurs moeten uitzonderingen genereren wanneer aan een of meer van de volgende voorwaarden wordt voldaan:
De methode kan de gedefinieerde functionaliteit niet voltooien. Als een parameter voor een methode bijvoorbeeld een ongeldige waarde heeft:
static void CopyObject(SampleClass original) { _ = original ?? throw new ArgumentException("Parameter cannot be null", nameof(original)); }
Er wordt een ongepaste aanroep van een object gemaakt op basis van de objectstatus. Een voorbeeld hiervan is het schrijven naar een bestand met het kenmerk Alleen-lezen. In gevallen waarin een objectstatus geen bewerking toestaat, genereert u een exemplaar van of een object op basis van InvalidOperationException een afleiding van deze klasse. De volgende code is een voorbeeld van een methode waarmee een InvalidOperationException object wordt gegenereerd:
public class ProgramLog { FileStream logFile = null!; public void OpenLog(FileInfo fileName, FileMode mode) { } public void WriteLog() { if (!logFile.CanWrite) { throw new InvalidOperationException("Logfile cannot be read-only"); } // Else write data to the log and return. } }
Wanneer een argument voor een methode een uitzondering veroorzaakt. In dit geval moet de oorspronkelijke uitzondering worden opgevangen en moet er een ArgumentException exemplaar worden gemaakt. De oorspronkelijke uitzondering moet worden doorgegeven aan de constructor van de ArgumentException parameter InnerException :
static int GetValueFromArray(int[] array, int index) { try { return array[index]; } catch (IndexOutOfRangeException e) { throw new ArgumentOutOfRangeException( "Parameter index is out of range.", e); } }
Notitie
In het voorgaande voorbeeld ziet u hoe u de
InnerException
eigenschap gebruikt. Het is opzettelijk vereenvoudigd. In de praktijk moet u controleren of een index zich in het bereik bevindt voordat u deze gebruikt. U kunt deze techniek gebruiken om een uitzondering te verpakken wanneer een lid van een parameter een uitzondering genereert die u niet kon verwachten voordat u het lid aanroept.
Uitzonderingen bevatten een eigenschap met de naam StackTrace. Deze tekenreeks bevat de naam van de methoden op de huidige aanroepstack, samen met de bestandsnaam en het regelnummer waar de uitzondering voor elke methode is gegenereerd. Een StackTrace object wordt automatisch gemaakt door de Common Language Runtime (CLR) vanaf het punt van de throw
instructie, zodat uitzonderingen moeten worden gegenereerd vanaf het punt waar de stack-trace moet beginnen.
Alle uitzonderingen bevatten een eigenschap met de naam Message. Deze tekenreeks moet worden ingesteld om de reden voor de uitzondering uit te leggen. Informatie die gevoelig is voor beveiliging, mag niet in de berichttekst worden geplaatst. Naast Message, ArgumentException bevat een eigenschap met de naam ParamName die moet worden ingesteld op de naam van het argument waardoor de uitzondering werd gegenereerd. In een eigenschapssetter ParamName moet worden ingesteld op value
.
Openbare en beveiligde methoden genereren uitzonderingen wanneer ze hun beoogde functies niet kunnen voltooien. De gegenereerde uitzonderingsklasse is de meest specifieke uitzondering die past bij de foutvoorwaarden. Deze uitzonderingen moeten worden gedocumenteerd als onderdeel van de klassefunctionaliteit en afgeleide klassen of updates van de oorspronkelijke klasse moeten hetzelfde gedrag behouden voor achterwaartse compatibiliteit.
Dingen die moeten worden vermeden bij het genereren van uitzonderingen
De volgende lijst identificeert procedures die moeten worden vermeden bij het genereren van uitzonderingen:
- Gebruik geen uitzonderingen om de stroom van een programma te wijzigen als onderdeel van gewone uitvoering. Gebruik uitzonderingen om foutvoorwaarden te rapporteren en af te handelen.
- Uitzonderingen mogen niet worden geretourneerd als een retourwaarde of parameter in plaats van te worden gegenereerd.
- Gooi System.Exceptionniet, System.SystemExceptionof System.NullReferenceExceptionSystem.IndexOutOfRangeException opzettelijk uit uw eigen broncode.
- Maak geen uitzonderingen die kunnen worden gegenereerd in de foutopsporingsmodus, maar niet in de releasemodus. Als u runtimefouten tijdens de ontwikkelingsfase wilt identificeren, gebruikt u In plaats daarvan Debug Assert.
Uitzonderingen in methoden voor het retourneren van taken
Methoden die met de async
modifier zijn gedeclareerd, hebben enkele speciale overwegingen bij uitzonderingen. Uitzonderingen die in een async
methode worden gegenereerd, worden opgeslagen in de geretourneerde taak en komen pas voor wanneer de taak bijvoorbeeld wordt gewacht. Zie Asynchrone uitzonderingen voor meer informatie over opgeslagen uitzonderingen.
U wordt aangeraden argumenten te valideren en eventuele bijbehorende uitzonderingen te genereren, zoals ArgumentException en ArgumentNullException, voordat u de asynchrone onderdelen van uw methoden invoert. Dat wil gezegd: deze validatieuitzondering moet synchroon ontstaan voordat het werk begint. In het volgende codefragment ziet u een voorbeeld waarin, als de uitzonderingen worden gegenereerd, de uitzonderingen synchroon worden weergegeven, terwijl de ArgumentExceptionInvalidOperationException uitzonderingen in de geretourneerde taak worden opgeslagen.
// Non-async, task-returning method.
// Within this method (but outside of the local function),
// any thrown exceptions emerge synchronously.
public static Task<Toast> ToastBreadAsync(int slices, int toastTime)
{
if (slices is < 1 or > 4)
{
throw new ArgumentException(
"You must specify between 1 and 4 slices of bread.",
nameof(slices));
}
if (toastTime < 1)
{
throw new ArgumentException(
"Toast time is too short.", nameof(toastTime));
}
return ToastBreadAsyncCore(slices, toastTime);
// Local async function.
// Within this function, any thrown exceptions are stored in the task.
static async Task<Toast> ToastBreadAsyncCore(int slices, int time)
{
for (int slice = 0; slice < slices; slice++)
{
Console.WriteLine("Putting a slice of bread in the toaster");
}
// Start toasting.
await Task.Delay(time);
if (time > 2_000)
{
throw new InvalidOperationException("The toaster is on fire!");
}
Console.WriteLine("Toast is ready!");
return new Toast();
}
}
Uitzonderingsklassen definiëren
Programma's kunnen een vooraf gedefinieerde uitzonderingsklasse genereren in de System naamruimte (behalve waar eerder vermeld) of hun eigen uitzonderingsklassen maken door hiervan af te leiden Exception. De afgeleide klassen moeten ten minste drie constructors definiëren: één parameterloze constructor, één die de berichteigenschap instelt en één die zowel de als InnerException de Message eigenschappen instelt. Voorbeeld:
[Serializable]
public class InvalidDepartmentException : Exception
{
public InvalidDepartmentException() : base() { }
public InvalidDepartmentException(string message) : base(message) { }
public InvalidDepartmentException(string message, Exception inner) : base(message, inner) { }
}
Voeg nieuwe eigenschappen toe aan de uitzonderingsklasse wanneer de gegevens die ze leveren nuttig zijn om de uitzondering op te lossen. Als er nieuwe eigenschappen worden toegevoegd aan de afgeleide uitzonderingsklasse, ToString()
moet deze worden overschreven om de toegevoegde informatie te retourneren.
C#-taalspecificatie
Zie Uitzonderingen en de instructie throw in de C#-taalspecificatie voor meer informatie. De taalspecificatie is de definitieve bron voor de C#-syntaxis en het gebruik.