Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Výjimky se používají k označení, že při spuštění programu došlo k chybě. Objekty výjimky, které popisují chybu, jsou vytvořeny a vyhozeny pomocí příkazu throw
nebo výrazu. Modul runtime pak vyhledá nejkomppatibilnější obslužnou rutinu výjimek.
Programátoři by měli vyvolat výjimky, pokud jsou splněny některé z následujících podmínek:
Metoda nemůže dokončit definované funkce. Pokud má například parametr metody neplatnou hodnotu:
static void CopyObject(SampleClass original) { _ = original ?? throw new ArgumentException("Parameter cannot be null", nameof(original)); }
Na základě stavu objektu je provedeno nevhodné volání. Jedním z příkladů může být pokus o zápis do souboru jen pro čtení. V případech, kdy stav objektu neumožňuje operaci, vyvolá instanci InvalidOperationException nebo objekt na základě odvození této třídy. Následující kód je příkladem metody, která vyvolá InvalidOperationException objekt:
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. } }
Když argument metody způsobí výjimku. V tomto případě by se měla zachytit původní výjimka a měla by se vytvořit instance ArgumentException. Původní výjimka by měla být předána konstruktoru ArgumentException jako parametr 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); } }
Poznámka
Předchozí příklad ukazuje, jak použít
InnerException
vlastnost. Je záměrně zjednodušená. V praxi byste měli před použitím zkontrolovat, jestli je index v rozsahu. Tuto techniku zabalení výjimky můžete použít, když člen parametru vyvolá výjimku, kterou jste nemohli před voláním člena předvídat.
Výjimky obsahují vlastnost s názvem StackTrace. Tento řetězec obsahuje názvy metod na aktuálním zásobníku volání společně s názvem souboru a číslem řádku, kde byla pro každou metodu vyvolána výjimka. Objekt StackTrace se vytvoří automaticky modulem CLR (Common Language Runtime) od místa příkazu throw
, takže výjimky musí být vyvolány z místa, kde má začínat trasování zásobníku.
Všechny výjimky obsahují vlastnost s názvem Message. Tento řetězec by měl být nastavený tak, aby vysvětlil důvod výjimky. Informace citlivé na zabezpečení by neměly být vloženy do textu zprávy. Kromě Messageobsahuje ArgumentException vlastnost s názvem ParamName, která by měla být nastavena na název argumentu, který způsobil výjimku vyvolání. Setter vlastností by měl nastavit ParamName na value
.
Veřejné a chráněné metody můžou vyvolat výjimky vždy, když nemůžou dokončit zamýšlené funkce. Vyvolaná třída výjimky je nejkonkrétnější dostupná výjimka, která odpovídá podmínkám chyby. Tyto výjimky by měly být zdokumentované jako součást funkcí třídy a odvozené třídy nebo aktualizace původní třídy by měly zachovat stejné chování pro zpětnou kompatibilitu.
Čemu se vyhnout při vyhazování výjimek
Následující seznam uvádí postupy, které se mají vyhnout při vyvolání výjimek:
- Nepoužívejte výjimky ke změně toku programu jako součást běžného provádění. Pomocí výjimek můžete hlásit a zpracovat chybové stavy.
- Výjimky by se neměly vracet jako návratová hodnota nebo parametr místo vyvolání.
- Nevyvolávejte System.Exception, System.SystemException, System.NullReferenceExceptionani záměrně System.IndexOutOfRangeException z vlastního zdrojového kódu.
- Nevytvávejte výjimky, které se dají vyvolat v režimu ladění, ale ne v režimu vydání. Pokud chcete identifikovat chyby za běhu během vývojové fáze, použijte místo toho příkaz Debug Assert.
Výjimky v metodách vracejících úkoly
Metody deklarované pomocí modifikátoru async
mají při výjimce několik zvláštních aspektů. Výjimky vyvolané v metodě async
jsou uloženy ve vrácené úloze a neobjeví se, dokud se například na úlohu nečeká. Další informace o uložených výjimkách naleznete v tématu Asynchronní výjimky.
Před zadáním asynchronních částí vašich metod doporučujeme ověřit argumenty a vyvolat odpovídající výjimky, jako jsou ArgumentException a ArgumentNullException. To znamená, že tyto výjimky ověřování by se měly objevit synchronně před zahájením práce. Následující fragment kódu ukazuje příklad, kdy pokud dojde k vyvolání výjimek, ArgumentException výjimky se objeví synchronně, zatímco InvalidOperationException by se uložily do vrácené úlohy.
// 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();
}
}
Definování tříd výjimek
Programy mohou vyvolat předdefinovanou třídu výjimky v oboru názvů System (s výjimkou případů, kdy byly dříve zaznamenány) nebo vytvořit vlastní třídy výjimek odvozením z Exception. Odvozené třídy by měly definovat alespoň tři konstruktory: jeden konstruktor bez parametrů, jeden, který nastavuje vlastnost zprávy, a jednu, která nastavuje Message i InnerException vlastnosti. Například:
[Serializable]
public class InvalidDepartmentException : Exception
{
public InvalidDepartmentException() : base() { }
public InvalidDepartmentException(string message) : base(message) { }
public InvalidDepartmentException(string message, Exception inner) : base(message, inner) { }
}
Přidejte do třídy výjimky nové vlastnosti, pokud jsou data, která poskytují, užitečná k vyřešení výjimky. Pokud jsou do odvozené třídy výjimky přidány nové vlastnosti, ToString()
by mělo být přepsáno, aby vrátilo přidané informace.
Specifikace jazyka C#
Další informace naleznete v tématu Výjimky a Příkaz throw v specifikace jazyka C#. Specifikace jazyka je konečným zdrojem syntaxe a použití jazyka C#.