Exception Třída
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Představuje chyby, ke kterým dochází během provádění aplikace.
public ref class Exception
public ref class Exception : System::Runtime::Serialization::ISerializable
public ref class Exception : System::Runtime::InteropServices::_Exception, System::Runtime::Serialization::ISerializable
public class Exception
public class Exception : System.Runtime.Serialization.ISerializable
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDual)]
[System.Serializable]
public class Exception : System.Runtime.Serialization.ISerializable
[System.Serializable]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public class Exception : System.Runtime.InteropServices._Exception, System.Runtime.Serialization.ISerializable
[System.Serializable]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public class Exception : System.Runtime.Serialization.ISerializable
type Exception = class
type Exception = class
interface ISerializable
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDual)>]
[<System.Serializable>]
type Exception = class
interface ISerializable
[<System.Serializable>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Exception = class
interface ISerializable
interface _Exception
[<System.Serializable>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Exception = class
interface ISerializable
Public Class Exception
Public Class Exception
Implements ISerializable
Public Class Exception
Implements _Exception, ISerializable
- Dědičnost
-
Exception
- Odvozené
- Atributy
- Implementuje
Příklady
Následující příklad ukazuje catch
blok (with
v jazyce F#), který je definován pro zpracování ArithmeticException chyb. Tento catch
blok také zachycuje DivideByZeroException chyby, protože DivideByZeroException je odvozen z ArithmeticException a neexistuje žádný catch
blok explicitně definovaný pro DivideByZeroException chyby.
using namespace System;
int main()
{
int x = 0;
try
{
int y = 100 / x;
}
catch ( ArithmeticException^ e )
{
Console::WriteLine( "ArithmeticException Handler: {0}", e );
}
catch ( Exception^ e )
{
Console::WriteLine( "Generic Exception Handler: {0}", e );
}
}
/*
This code example produces the following results:
ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
at main()
*/
using System;
class ExceptionTestClass
{
public static void Main()
{
int x = 0;
try
{
int y = 100 / x;
}
catch (ArithmeticException e)
{
Console.WriteLine($"ArithmeticException Handler: {e}");
}
catch (Exception e)
{
Console.WriteLine($"Generic Exception Handler: {e}");
}
}
}
/*
This code example produces the following results:
ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
at ExceptionTestClass.Main()
*/
module ExceptionTestModule
open System
let x = 0
try
let y = 100 / x
()
with
| :? ArithmeticException as e ->
printfn $"ArithmeticException Handler: {e}"
| e ->
printfn $"Generic Exception Handler: {e}"
// This code example produces the following results:
// ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
// at <StartupCode$fs>.$ExceptionTestModule.main@()
Class ExceptionTestClass
Public Shared Sub Main()
Dim x As Integer = 0
Try
Dim y As Integer = 100 / x
Catch e As ArithmeticException
Console.WriteLine("ArithmeticException Handler: {0}", e.ToString())
Catch e As Exception
Console.WriteLine("Generic Exception Handler: {0}", e.ToString())
End Try
End Sub
End Class
'
'This code example produces the following results:
'
'ArithmeticException Handler: System.OverflowException: Arithmetic operation resulted in an overflow.
' at ExceptionTestClass.Main()
'
Poznámky
Tato třída je základní třídou pro všechny výjimky. Když dojde k chybě, systém nebo aktuálně spuštěná aplikace ji hlásí vyvoláním výjimky, která obsahuje informace o chybě. Po vyvolání výjimky ji zpracuje aplikace nebo výchozí obslužná rutina výjimky.
V této části:
Chyby a výjimky
Bloky try/catch
Funkce typu výjimky
Vlastnosti třídy výjimky
Otázky výkonu
Opětovné vyvolání výjimky
Volba standardních výjimek
Implementace vlastních výjimek
Chyby a výjimky
K chybám za běhu může docházet z různých důvodů. Ne všechny chyby by ale měly být ve vašem kódu zpracovány jako výjimky. Tady jsou některé kategorie chyb, ke kterým může dojít za běhu, a vhodné způsoby, jak na ně reagovat.
Chyby využití. Chyba použití představuje chybu v logice programu, která může vést k výjimce. Tato chyba by však neměla být vyřešena zpracováním výjimek, ale úpravou chybného kódu. Například přepsání Object.Equals(Object) metody v následujícím příkladu předpokládá, že
obj
argument musí být vždy non-null.using System; public class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } public override int GetHashCode() { return this.Name.GetHashCode(); } public override bool Equals(object obj) { // This implementation contains an error in program logic: // It assumes that the obj argument is not null. Person p = (Person) obj; return this.Name.Equals(p.Name); } } public class Example { public static void Main() { Person p1 = new Person(); p1.Name = "John"; Person p2 = null; // The following throws a NullReferenceException. Console.WriteLine("p1 = p2: {0}", p1.Equals(p2)); } }
// In F#, null is not a valid state for declared types // without 'AllowNullLiteralAttribute' [<AllowNullLiteral>] type Person() = member val Name = "" with get, set override this.GetHashCode() = this.Name.GetHashCode() override this.Equals(obj) = // This implementation contains an error in program logic: // It assumes that the obj argument is not null. let p = obj :?> Person this.Name.Equals p.Name let p1 = Person() p1.Name <- "John" let p2: Person = null // The following throws a NullReferenceException. printfn $"p1 = p2: {p1.Equals p2}"
Public Class Person Private _name As String Public Property Name As String Get Return _name End Get Set _name = value End Set End Property Public Overrides Function Equals(obj As Object) As Boolean ' This implementation contains an error in program logic: ' It assumes that the obj argument is not null. Dim p As Person = CType(obj, Person) Return Me.Name.Equals(p.Name) End Function End Class Module Example Public Sub Main() Dim p1 As New Person() p1.Name = "John" Dim p2 As Person = Nothing ' The following throws a NullReferenceException. Console.WriteLine("p1 = p2: {0}", p1.Equals(p2)) End Sub End Module
Výjimku NullReferenceException , která je výsledkem
obj
,null
lze odstranit úpravou zdrojového kódu tak, aby explicitně testoval hodnotu null před voláním Object.Equals přepsání a následným opětovným kompilací. Následující příklad obsahuje opravený zdrojový kód, který zpracovávánull
argument.using System; public class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } public override int GetHashCode() { return this.Name.GetHashCode(); } public override bool Equals(object obj) { // This implementation handles a null obj argument. Person p = obj as Person; if (p == null) return false; else return this.Name.Equals(p.Name); } } public class Example { public static void Main() { Person p1 = new Person(); p1.Name = "John"; Person p2 = null; Console.WriteLine("p1 = p2: {0}", p1.Equals(p2)); } } // The example displays the following output: // p1 = p2: False
// In F#, null is not a valid state for declared types // without 'AllowNullLiteralAttribute' [<AllowNullLiteral>] type Person() = member val Name = "" with get, set override this.GetHashCode() = this.Name.GetHashCode() override this.Equals(obj) = // This implementation handles a null obj argument. match obj with | :? Person as p -> this.Name.Equals p.Name | _ -> false let p1 = Person() p1.Name <- "John" let p2: Person = null printfn $"p1 = p2: {p1.Equals p2}" // The example displays the following output: // p1 = p2: False
Public Class Person Private _name As String Public Property Name As String Get Return _name End Get Set _name = value End Set End Property Public Overrides Function Equals(obj As Object) As Boolean ' This implementation handles a null obj argument. Dim p As Person = TryCast(obj, Person) If p Is Nothing Then Return False Else Return Me.Name.Equals(p.Name) End If End Function End Class Module Example Public Sub Main() Dim p1 As New Person() p1.Name = "John" Dim p2 As Person = Nothing Console.WriteLine("p1 = p2: {0}", p1.Equals(p2)) End Sub End Module ' The example displays the following output: ' p1 = p2: False
Místo použití zpracování výjimek pro chyby použití můžete použít metodu Debug.Assert k identifikaci chyb použití v sestaveních ladění a metodu Trace.Assert k identifikaci chyb použití v sestaveních ladění i verzí. Další informace najdete v tématu Kontrolní výrazy ve spravovaném kódu.
Chyby programu. Chyba programu je chyba za běhu, které nelze nutně zabránit napsáním kódu bez chyb.
V některých případech může chyba programu odrážet očekávanou nebo rutinní chybovou podmínku. V takovém případě můžete chtít zabránit použití zpracování výjimek k řešení chyby programu a místo toho zkusit operaci zopakovat. Pokud se například očekává, že uživatel zadá datum v určitém formátu, můžete analyzovat řetězec kalendářního data voláním DateTime.TryParseExact metody, která vrátí Boolean hodnotu, která označuje, zda byla operace parse úspěšná, místo použití DateTime.ParseExact metody, která vyvolá FormatException výjimku, pokud řetězec kalendářního data nelze převést na DateTime hodnotu. Podobně platí, že pokud se uživatel pokusí otevřít soubor, který neexistuje, můžete nejprve zavolat metodu File.Exists , která zkontroluje, jestli soubor existuje, a pokud ne, zobrazí uživateli výzvu, zda ho chce vytvořit.
V jiných případech chyba programu odráží neočekávaný chybový stav, který je možné zpracovat ve vašem kódu. I když jste například zkontrolovali, jestli soubor existuje, může být před otevřením odstraněn nebo poškozen. V takovém případě může pokus o otevření souboru vytvořením instance objektu StreamReader nebo voláním Open metody vyvolat FileNotFoundException výjimku. V těchto případech byste měli k zotavení z chyby použít zpracování výjimek.
Selhání systému. Selhání systému je chyba za běhu, kterou nelze zpracovat programově smysluplným způsobem. Například jakákoli metoda může vyvolat výjimku OutOfMemoryException , pokud modul CLR (Common Language Runtime) nemůže přidělit další paměť. Selhání systému se obvykle nezpracují pomocí zpracování výjimek. Místo toho můžete použít událost, například AppDomain.UnhandledException a volat metodu Environment.FailFast k protokolování informací o výjimce a upozornit uživatele na selhání před ukončením aplikace.
Bloky try/catch
Common Language Runtime poskytuje model zpracování výjimek, který je založený na reprezentaci výjimek jako objektů a oddělení kódu programu a kódu zpracování výjimek do try
bloků a catch
bloků. Může existovat jeden nebo více catch
bloků, z nichž každý je navržený pro zpracování určitého typu výjimky, nebo jeden blok navržený tak, aby zachytil konkrétnější výjimku než jiný blok.
Pokud aplikace zpracovává výjimky, ke kterým dochází během provádění bloku kódu aplikace, musí být kód umístěn v příkazu try
a nazývá se try
blok. Kód aplikace, který zpracovává výjimky vyvolané blokem try
, se umístí do catch
příkazu a nazývá se catch
blok. K bloku je přidruženo try
nula nebo více catch
bloků a každý catch
blok obsahuje filtr typů, který určuje typy výjimek, které zpracovává.
Pokud dojde k výjimce try
v bloku, systém prohledá přidružené catch
bloky v pořadí, ve které se zobrazí v kódu aplikace, dokud nenajde catch
blok, který zpracovává výjimku. Blok catch
zpracovává výjimku typu T
, pokud je zadán T
filtr typu bloku catch nebo jakýkoli typ, který T
je odvozen od. Systém přestane hledat poté, co najde první catch
blok, který zpracovává výjimku. Z tohoto důvodu musí být v kódu aplikace před blokem, catch
který zpracovává jeho základní typy, zadán catch
blok, který zpracovává typ, jak je znázorněno v příkladu, který následuje po této části. Blok zachycení, který zpracovává System.Exception
, je zadán jako poslední.
Pokud žádný z catch
bloků přidružených k aktuálnímu try
bloku nezvládá výjimku a aktuální try
blok je vnořený do jiných try
bloků aktuálního volání, catch
budou prohledány bloky přidružené k dalšímu ohraničujícímu try
bloku. Pokud se nenajde žádný catch
blok výjimky, systém vyhledá předchozí úrovně vnoření v aktuálním volání. Pokud se v aktuálním volání nenajde žádný catch
blok pro výjimku, je výjimka předána zásobníku volání a předchozí rámec zásobníku catch
se vyhledá blok, který zpracovává výjimku. Hledání zásobníku volání pokračuje, dokud se nezpracuje výjimka nebo dokud v zásobníku volání nebudou existovat žádné další rámce. Pokud je dosaženo horní části zásobníku volání bez nalezení catch
bloku, který zpracovává výjimku, výchozí obslužná rutina výjimky ji zpracuje a aplikace se ukončí.
F# try.. s výrazem
F# nepoužívá catch
bloky. Místo toho se vyvolaná výjimka shoduje se vzorem pomocí jednoho with
bloku. Vzhledem k tomu, že se jedná o výraz, nikoli příkaz, musí všechny cesty vrátit stejný typ. Další informace najdete v tématu Zkuste... pomocí výrazu.
Funkce typu výjimky
Typy výjimek podporují následující funkce:
Text čitelný pro člověka, který popisuje chybu. Když dojde k výjimce, modul runtime zpřístupní textovou zprávu, která uživatele informuje o povaze chyby a navrhne akci k vyřešení problému. Tato textová zpráva je uložena ve Message vlastnosti objektu výjimky. Při vytváření objektu výjimky můžete konstruktoru předat textový řetězec, který popisuje podrobnosti o této konkrétní výjimce. Pokud konstruktoru není zadán žádný argument chybové zprávy, použije se výchozí chybová zpráva. Další informace najdete ve Message vlastnosti .
Stav zásobníku volání při vyvolání výjimky. Vlastnost StackTrace nese trasování zásobníku, které lze použít k určení, kde v kódu dochází k chybě. Trasování zásobníku uvádí všechny volané metody a čísla řádků ve zdrojovém souboru, kde jsou volání provedena.
Vlastnosti třídy výjimky
Třída Exception obsahuje řadu vlastností, které pomáhají identifikovat umístění kódu, typ, soubor nápovědy a důvod výjimky: StackTrace, InnerException, , Message, HelpLinkHResult, Source, TargetSitea Data.
Pokud mezi dvěma nebo více výjimkami existuje kauzální vztah, InnerException vlastnost tyto informace zachová. Vnější výjimka je vyvolán v reakci na tuto vnitřní výjimku. Kód, který zpracovává vnější výjimku, může použít informace z dřívější vnitřní výjimky k vhodnějšímu zpracování chyby. Doplňující informace o výjimce mohou být uloženy jako kolekce párů klíč/hodnota ve Data vlastnosti .
Řetězec chybové zprávy, který je předán konstruktoru při vytváření objektu výjimky, by měl být lokalizován a lze jej zadat ze souboru prostředků pomocí ResourceManager třídy . Další informace o lokalizovaných prostředcích najdete v tématech Vytváření satelitních sestavení a balení a nasazování prostředků .
Pokud chcete uživateli poskytnout rozsáhlé informace o tom, proč k výjimce došlo, HelpLink může vlastnost obsahovat adresu URL (nebo URN) souboru nápovědy.
Třída Exception používá COR_E_EXCEPTION HRESULT, která má hodnotu 0x80131500.
Seznam počátečních hodnot vlastností pro instanci Exception třídy naleznete v Exception konstruktorech.
Otázky výkonu
Vyvolání nebo zpracování výjimky spotřebovává značné množství systémových prostředků a doby provádění. Vyvolání výjimek pouze pro zpracování skutečně výjimečných podmínek, nikoli pro zpracování předvídatelných událostí nebo řízení toku. Například v některých případech, například při vývoji knihovny tříd, je vhodné vyvolat výjimku, pokud je argument metody neplatný, protože očekáváte, že metoda bude volána s platnými parametry. Neplatný argument metody, pokud není výsledkem chyby použití, znamená, že došlo k něčemu mimořádnému. Naopak nevyvolávejte výjimku, pokud je uživatelský vstup neplatný, protože můžete očekávat, že uživatelé budou občas zadávat neplatná data. Místo toho poskytněte mechanismus opakování, aby uživatelé mohli zadat platný vstup. Výjimky byste také neměli používat ke zpracování chyb použití. Místo toho použijte kontrolní výrazy k identifikaci a opravě chyb použití.
Kromě toho nevyvolejte výjimku, pokud je návratový kód dostačující. nepřevádí návratový kód na výjimku; a pravidelně nezachytávají výjimku, ignorujte ji a pak pokračujte ve zpracování.
Opětovné vyvolání výjimky
V mnoha případech chce obslužná rutina výjimky jednoduše předat výjimku volajícímu. K tomu nejčastěji dochází v:
Knihovna tříd, která zase zalamuje volání metod v knihovně tříd rozhraní .NET Framework nebo jiných knihovnách tříd.
Aplikace nebo knihovna, u které dojde k závažné výjimce. Obslužná rutina výjimky může výjimku protokolovat a pak znovu vyvolat výjimku.
Doporučeným způsobem opětovného vyvolání výjimky je jednoduše použít příkaz throw v jazyce C#, funkci reraise v jazyce F# a příkaz Throw v jazyce Visual Basic bez zahrnutí výrazu. Tím se zajistí, že se při šíření výjimky do volajícího zachovají všechny informace o zásobníku volání. Toto dokládá následující příklad. Metoda FindOccurrences
rozšíření řetězce zabalí jedno nebo více volání metody bez String.IndexOf(String, Int32) předchozího ověření argumentů.
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
public static class Library
{
public static int[] FindOccurrences(this String s, String f)
{
var indexes = new List<int>();
int currentIndex = 0;
try {
while (currentIndex >= 0 && currentIndex < s.Length) {
currentIndex = s.IndexOf(f, currentIndex);
if (currentIndex >= 0) {
indexes.Add(currentIndex);
currentIndex++;
}
}
}
catch (ArgumentNullException e) {
// Perform some action here, such as logging this exception.
throw;
}
return indexes.ToArray();
}
}
open System
module Library =
let findOccurrences (s: string) (f: string) =
let indexes = ResizeArray()
let mutable currentIndex = 0
try
while currentIndex >= 0 && currentIndex < s.Length do
currentIndex <- s.IndexOf(f, currentIndex)
if currentIndex >= 0 then
indexes.Add currentIndex
currentIndex <- currentIndex + 1
with :? ArgumentNullException ->
// Perform some action here, such as logging this exception.
reraise ()
indexes.ToArray()
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices
Public Module Library
<Extension()>
Public Function FindOccurrences(s As String, f As String) As Integer()
Dim indexes As New List(Of Integer)
Dim currentIndex As Integer = 0
Try
Do While currentIndex >= 0 And currentIndex < s.Length
currentIndex = s.IndexOf(f, currentIndex)
If currentIndex >= 0 Then
indexes.Add(currentIndex)
currentIndex += 1
End If
Loop
Catch e As ArgumentNullException
' Perform some action here, such as logging this exception.
Throw
End Try
Return indexes.ToArray()
End Function
End Module
Volající pak zavolá FindOccurrences
dvakrát. Při druhém volání FindOccurrences
metody volající předá null
jako hledaný řetězec, což způsobí String.IndexOf(String, Int32) , že metoda vyvolá výjimku ArgumentNullException . Tato výjimka je zpracována metodou FindOccurrences
a předána zpět volajícímu. Vzhledem k tomu, že se příkaz throw používá bez výrazu, výstup z příkladu ukazuje, že zásobník volání je zachován.
public class Example
{
public static void Main()
{
String s = "It was a cold day when...";
int[] indexes = s.FindOccurrences("a");
ShowOccurrences(s, "a", indexes);
Console.WriteLine();
String toFind = null;
try {
indexes = s.FindOccurrences(toFind);
ShowOccurrences(s, toFind, indexes);
}
catch (ArgumentNullException e) {
Console.WriteLine("An exception ({0}) occurred.",
e.GetType().Name);
Console.WriteLine("Message:\n {0}\n", e.Message);
Console.WriteLine("Stack Trace:\n {0}\n", e.StackTrace);
}
}
private static void ShowOccurrences(String s, String toFind, int[] indexes)
{
Console.Write("'{0}' occurs at the following character positions: ",
toFind);
for (int ctr = 0; ctr < indexes.Length; ctr++)
Console.Write("{0}{1}", indexes[ctr],
ctr == indexes.Length - 1 ? "" : ", ");
Console.WriteLine();
}
}
// The example displays the following output:
// 'a' occurs at the following character positions: 4, 7, 15
//
// An exception (ArgumentNullException) occurred.
// Message:
// Value cannot be null.
// Parameter name: value
//
// Stack Trace:
// at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
// ngComparison comparisonType)
// at Library.FindOccurrences(String s, String f)
// at Example.Main()
open Library
let showOccurrences toFind (indexes: int[]) =
printf $"'{toFind}' occurs at the following character positions: "
for i = 0 to indexes.Length - 1 do
printf $"""{indexes[i]}{if i = indexes.Length - 1 then "" else ", "}"""
printfn ""
let s = "It was a cold day when..."
let indexes = findOccurrences s "a"
showOccurrences "a" indexes
printfn ""
let toFind: string = null
try
let indexes = findOccurrences s toFind
showOccurrences toFind indexes
with :? ArgumentNullException as e ->
printfn $"An exception ({e.GetType().Name}) occurred."
printfn $"Message:\n {e.Message}\n"
printfn $"Stack Trace:\n {e.StackTrace}\n"
// The example displays the following output:
// 'a' occurs at the following character positions: 4, 7, 15
//
// An exception (ArgumentNullException) occurred.
// Message:
// Value cannot be null. (Parameter 'value')
//
// Stack Trace:
// at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
// ngComparison comparisonType)
// at Library.findOccurrences(String s, String f)
// at <StartupCode$fs>.main@()
Module Example
Public Sub Main()
Dim s As String = "It was a cold day when..."
Dim indexes() As Integer = s.FindOccurrences("a")
ShowOccurrences(s, "a", indexes)
Console.WriteLine()
Dim toFind As String = Nothing
Try
indexes = s.FindOccurrences(toFind)
ShowOccurrences(s, toFind, indexes)
Catch e As ArgumentNullException
Console.WriteLine("An exception ({0}) occurred.",
e.GetType().Name)
Console.WriteLine("Message:{0} {1}{0}", vbCrLf, e.Message)
Console.WriteLine("Stack Trace:{0} {1}{0}", vbCrLf, e.StackTrace)
End Try
End Sub
Private Sub ShowOccurrences(s As String, toFind As String, indexes As Integer())
Console.Write("'{0}' occurs at the following character positions: ",
toFind)
For ctr As Integer = 0 To indexes.Length - 1
Console.Write("{0}{1}", indexes(ctr),
If(ctr = indexes.Length - 1, "", ", "))
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' 'a' occurs at the following character positions: 4, 7, 15
'
' An exception (ArgumentNullException) occurred.
' Message:
' Value cannot be null.
' Parameter name: value
'
' Stack Trace:
' at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
' ngComparison comparisonType)
' at Library.FindOccurrences(String s, String f)
' at Example.Main()
Naopak pokud je výjimka znovu vyvolán pomocí
throw e;
Throw e
raise e
celý zásobník volání se nezachová a příklad by vygeneroval následující výstup:
'a' occurs at the following character positions: 4, 7, 15
An exception (ArgumentNullException) occurred.
Message:
Value cannot be null.
Parameter name: value
Stack Trace:
at Library.FindOccurrences(String s, String f)
at Example.Main()
Trochu složitější alternativou je vyvolání nové výjimky a zachování informací o zásobníku volání původní výjimky ve vnitřní výjimce. Volající pak může použít vlastnost nové výjimky InnerException k načtení rámce zásobníku a dalších informací o původní výjimce. V tomto případě je příkaz throw následující:
throw new ArgumentNullException("You must supply a search string.",
e);
raise (ArgumentNullException("You must supply a search string.", e) )
Throw New ArgumentNullException("You must supply a search string.",
e)
Uživatelský kód, který zpracovává výjimku, musí vědět, že InnerException vlastnost obsahuje informace o původní výjimce, jak ukazuje následující obslužná rutina výjimky.
try {
indexes = s.FindOccurrences(toFind);
ShowOccurrences(s, toFind, indexes);
}
catch (ArgumentNullException e) {
Console.WriteLine("An exception ({0}) occurred.",
e.GetType().Name);
Console.WriteLine(" Message:\n{0}", e.Message);
Console.WriteLine(" Stack Trace:\n {0}", e.StackTrace);
Exception ie = e.InnerException;
if (ie != null) {
Console.WriteLine(" The Inner Exception:");
Console.WriteLine(" Exception Name: {0}", ie.GetType().Name);
Console.WriteLine(" Message: {0}\n", ie.Message);
Console.WriteLine(" Stack Trace:\n {0}\n", ie.StackTrace);
}
}
// The example displays the following output:
// 'a' occurs at the following character positions: 4, 7, 15
//
// An exception (ArgumentNullException) occurred.
// Message: You must supply a search string.
//
// Stack Trace:
// at Library.FindOccurrences(String s, String f)
// at Example.Main()
//
// The Inner Exception:
// Exception Name: ArgumentNullException
// Message: Value cannot be null.
// Parameter name: value
//
// Stack Trace:
// at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
// ngComparison comparisonType)
// at Library.FindOccurrences(String s, String f)
try
let indexes = findOccurrences s toFind
showOccurrences toFind indexes
with :? ArgumentNullException as e ->
printfn $"An exception ({e.GetType().Name}) occurred."
printfn $" Message:\n{e.Message}"
printfn $" Stack Trace:\n {e.StackTrace}"
let ie = e.InnerException
if ie <> null then
printfn " The Inner Exception:"
printfn $" Exception Name: {ie.GetType().Name}"
printfn $" Message: {ie.Message}\n"
printfn $" Stack Trace:\n {ie.StackTrace}\n"
// The example displays the following output:
// 'a' occurs at the following character positions: 4, 7, 15
//
// An exception (ArgumentNullException) occurred.
// Message: You must supply a search string.
//
// Stack Trace:
// at Library.FindOccurrences(String s, String f)
// at Example.Main()
//
// The Inner Exception:
// Exception Name: ArgumentNullException
// Message: Value cannot be null.
// Parameter name: value
//
// Stack Trace:
// at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
// ngComparison comparisonType)
// at Library.FindOccurrences(String s, String f)
Try
indexes = s.FindOccurrences(toFind)
ShowOccurrences(s, toFind, indexes)
Catch e As ArgumentNullException
Console.WriteLine("An exception ({0}) occurred.",
e.GetType().Name)
Console.WriteLine(" Message: {1}{0}", vbCrLf, e.Message)
Console.WriteLine(" Stack Trace:{0} {1}{0}", vbCrLf, e.StackTrace)
Dim ie As Exception = e.InnerException
If ie IsNot Nothing Then
Console.WriteLine(" The Inner Exception:")
Console.WriteLine(" Exception Name: {0}", ie.GetType().Name)
Console.WriteLine(" Message: {1}{0}", vbCrLf, ie.Message)
Console.WriteLine(" Stack Trace:{0} {1}{0}", vbCrLf, ie.StackTrace)
End If
End Try
' The example displays the following output:
' 'a' occurs at the following character positions: 4, 7, 15
'
' An exception (ArgumentNullException) occurred.
' Message: You must supply a search string.
'
' Stack Trace:
' at Library.FindOccurrences(String s, String f)
' at Example.Main()
'
' The Inner Exception:
' Exception Name: ArgumentNullException
' Message: Value cannot be null.
' Parameter name: value
'
' Stack Trace:
' at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
' ngComparison comparisonType)
' at Library.FindOccurrences(String s, String f)
Volba standardních výjimek
Pokud potřebujete vyvolat výjimku, můžete často použít existující typ výjimky v rozhraní .NET Framework místo implementace vlastní výjimky. Měli byste použít standardní typ výjimky za těchto dvou podmínek:
Vyvoláváte výjimku, která je způsobená chybou použití (to znamená chybou v programové logice, kterou udělal vývojář, který volá vaši metodu). Obvykle byste vyvolali výjimku, například ArgumentException, ArgumentNullException, InvalidOperationExceptionnebo NotSupportedException. Řetězec, který zadáte konstruktoru objektu výjimky při vytváření instance objektu výjimky, by měl popisovat chybu, aby ji vývojář mohl opravit. Další informace najdete ve Message vlastnosti .
Zpracováváte chybu, která může být sdělena volajícímu s existující výjimkou rozhraní .NET Framework. Měli byste vyvolat co nejvíce odvozenou výjimku. Pokud například metoda vyžaduje, aby argument byl platným členem typu výčtu, měli byste vyvolat InvalidEnumArgumentException (nejvíce odvozenou třídu) místo ArgumentException.
Následující tabulka uvádí běžné typy výjimek a podmínky, za kterých byste je vyvolali.
Výjimka | Podmínka |
---|---|
ArgumentException | Argument, který není null, který je předán metodě, je neplatný. |
ArgumentNullException | Argument, který se předá metodě, je null . |
ArgumentOutOfRangeException | Argument je mimo rozsah platných hodnot. |
DirectoryNotFoundException | Část cesty k adresáři není platná. |
DivideByZeroException | Jmenovatel v celočíselné operaci nebo Decimal operaci dělení je nula. |
DriveNotFoundException | Jednotka je nedostupná nebo neexistuje. |
FileNotFoundException | Soubor neexistuje. |
FormatException | Hodnota není v odpovídajícím formátu, který by se převeďte z řetězce metodou převodu, jako Parse je . |
IndexOutOfRangeException | Index je mimo hranice pole nebo kolekce. |
InvalidOperationException | Volání metody je v aktuálním stavu objektu neplatné. |
KeyNotFoundException | Zadaný klíč pro přístup ke členu v kolekci nebyl nalezen. |
NotImplementedException | Metoda nebo operace není implementována. |
NotSupportedException | Metoda nebo operace nejsou podporovány. |
ObjectDisposedException | U objektu, který byl odstraněn, se provede operace. |
OverflowException | Výsledkem aritmetické operace, přetypování nebo převodu je přetečení. |
PathTooLongException | Cesta nebo název souboru překračuje maximální délku definovanou systémem. |
PlatformNotSupportedException | Operace není na aktuální platformě podporovaná. |
RankException | Metodě je předáno pole s nesprávným počtem dimenzí. |
TimeoutException | Časový interval přidělený operaci vypršel. |
UriFormatException | Použije se neplatný identifikátor URI (Uniform Resource Identifier). |
Implementace vlastních výjimek
V následujících případech použití existující výjimky rozhraní .NET Framework ke zpracování chybového stavu není dostatečné:
Pokud výjimka odráží jedinečnou chybu programu, kterou nelze namapovat na existující výjimku rozhraní .NET Framework.
Pokud výjimka vyžaduje zpracování, které se liší od zpracování, které je vhodné pro existující výjimku rozhraní .NET Framework, nebo musí být výjimka nejednoznačná z podobné výjimky. Pokud například vyvoláte ArgumentOutOfRangeException výjimku při analýze číselné reprezentace řetězce, který je mimo rozsah cílového integrálního typu, nebudete chtít použít stejnou výjimku pro chybu, která je výsledkem toho, že volající při volání metody nezadá příslušné omezené hodnoty.
Třída Exception je základní třídou všech výjimek v rozhraní .NET Framework. Mnoho odvozených tříd spoléhá na zděděné chování členů Exception třídy; nepřepíší členy Exception, ani nedefinují žádné jedinečné členy.
Definování vlastní třídy výjimek:
Definujte třídu, která dědí z Exceptiontřídy . V případě potřeby definujte všechny jedinečné členy, které vaše třída potřebuje k poskytnutí dalších informací o výjimce. Například třída obsahuje ParamName vlastnost, která určuje název parametru, ArgumentException jehož argument způsobil výjimku, a RegexMatchTimeoutException vlastnost obsahuje MatchTimeout vlastnost, která označuje interval časového limitu.
V případě potřeby přepište všechny zděděné členy, jejichž funkce chcete změnit nebo upravit. Všimněte si, že většina existujících odvozených Exception tříd nepřepíše chování zděděných členů.
Určete, zda je vlastní objekt výjimky serializovatelný. Serializace umožňuje uložit informace o výjimce a umožňuje, aby informace o výjimce byly sdíleny serverem a klientským proxy serverem v kontextu vzdálené komunikace. Chcete-li objekt výjimky serializovat, označte ho atributem SerializableAttribute .
Definujte konstruktory třídy výjimky. Třídy výjimek mají obvykle jeden nebo více následujících konstruktorů:
Exception(), který používá výchozí hodnoty k inicializaci vlastností nového objektu výjimky.
Exception(String), který inicializuje nový objekt výjimky se zadanou chybovou zprávou.
Exception(String, Exception), který inicializuje nový objekt výjimky se zadanou chybovou zprávou a vnitřní výjimkou.
Exception(SerializationInfo, StreamingContext), což je
protected
konstruktor, který inicializuje nový objekt výjimky ze serializovaných dat. Tento konstruktor byste měli implementovat, pokud jste se rozhodli, aby objekt výjimky serializovatelný.
Následující příklad znázorňuje použití vlastní třídy výjimek. Definuje výjimku, která se vyvolá, když se klient pokusí načíst posloupnost prvočísek NotPrimeException
zadáním počátečního čísla, které není prvočíslo. Výjimka definuje novou vlastnost , NonPrime
která vrací jiné než prvočíslo, které způsobilo výjimku. Kromě implementace chráněného konstruktoru bez parametrů a konstruktoru s SerializationInfo parametry a StreamingContext pro serializaci třída NotPrimeException
definuje tři další konstruktory pro podporu NonPrime
vlastnosti. Každý konstruktor volá konstruktor základní třídy kromě zachování hodnoty jiného než primárního čísla. Třída NotPrimeException
je také označena atributem SerializableAttribute .
using System;
using System.Runtime.Serialization;
[Serializable()]
public class NotPrimeException : Exception
{
private int notAPrime;
protected NotPrimeException()
: base()
{ }
public NotPrimeException(int value) :
base(String.Format("{0} is not a prime number.", value))
{
notAPrime = value;
}
public NotPrimeException(int value, string message)
: base(message)
{
notAPrime = value;
}
public NotPrimeException(int value, string message, Exception innerException) :
base(message, innerException)
{
notAPrime = value;
}
protected NotPrimeException(SerializationInfo info,
StreamingContext context)
: base(info, context)
{ }
public int NonPrime
{ get { return notAPrime; } }
}
namespace global
open System
open System.Runtime.Serialization
[<Serializable>]
type NotPrimeException =
inherit Exception
val notAPrime: int
member this.NonPrime =
this.notAPrime
new (value) =
{ inherit Exception($"%i{value} is not a prime number."); notAPrime = value }
new (value, message) =
{ inherit Exception(message); notAPrime = value }
new (value, message, innerException: Exception) =
{ inherit Exception(message, innerException); notAPrime = value }
// F# does not support protected members
new () =
{ inherit Exception(); notAPrime = 0 }
new (info: SerializationInfo, context: StreamingContext) =
{ inherit Exception(info, context); notAPrime = 0 }
Imports System.Runtime.Serialization
<Serializable()> _
Public Class NotPrimeException : Inherits Exception
Private notAPrime As Integer
Protected Sub New()
MyBase.New()
End Sub
Public Sub New(value As Integer)
MyBase.New(String.Format("{0} is not a prime number.", value))
notAPrime = value
End Sub
Public Sub New(value As Integer, message As String)
MyBase.New(message)
notAPrime = value
End Sub
Public Sub New(value As Integer, message As String, innerException As Exception)
MyBase.New(message, innerException)
notAPrime = value
End Sub
Protected Sub New(info As SerializationInfo,
context As StreamingContext)
MyBase.New(info, context)
End Sub
Public ReadOnly Property NonPrime As Integer
Get
Return notAPrime
End Get
End Property
End Class
Třída zobrazená PrimeNumberGenerator
v následujícím příkladu používá síto Eratosthenes k výpočtu posloupnosti prvočísek od 2 do limitu určeného klientem ve volání jeho konstruktoru třídy. Metoda GetPrimesFrom
vrátí všechna prvočísla, která jsou větší než nebo rovna zadanému dolnímu limitu NotPrimeException
, ale vyvolá, pokud tento dolní limit není prvočíslo.
using System;
using System.Collections.Generic;
[Serializable]
public class PrimeNumberGenerator
{
private const int START = 2;
private int maxUpperBound = 10000000;
private int upperBound;
private bool[] primeTable;
private List<int> primes = new List<int>();
public PrimeNumberGenerator(int upperBound)
{
if (upperBound > maxUpperBound)
{
string message = String.Format(
"{0} exceeds the maximum upper bound of {1}.",
upperBound, maxUpperBound);
throw new ArgumentOutOfRangeException(message);
}
this.upperBound = upperBound;
// Create array and mark 0, 1 as not prime (True).
primeTable = new bool[upperBound + 1];
primeTable[0] = true;
primeTable[1] = true;
// Use Sieve of Eratosthenes to determine prime numbers.
for (int ctr = START; ctr <= (int)Math.Ceiling(Math.Sqrt(upperBound));
ctr++)
{
if (primeTable[ctr]) continue;
for (int multiplier = ctr; multiplier <= upperBound / ctr; multiplier++)
if (ctr * multiplier <= upperBound) primeTable[ctr * multiplier] = true;
}
// Populate array with prime number information.
int index = START;
while (index != -1)
{
index = Array.FindIndex(primeTable, index, (flag) => !flag);
if (index >= 1)
{
primes.Add(index);
index++;
}
}
}
public int[] GetAllPrimes()
{
return primes.ToArray();
}
public int[] GetPrimesFrom(int prime)
{
int start = primes.FindIndex((value) => value == prime);
if (start < 0)
throw new NotPrimeException(prime, String.Format("{0} is not a prime number.", prime));
else
return primes.FindAll((value) => value >= prime).ToArray();
}
}
namespace global
open System
[<Serializable>]
type PrimeNumberGenerator(upperBound) =
let start = 2
let maxUpperBound = 10000000
let primes = ResizeArray()
let primeTable =
upperBound + 1
|> Array.zeroCreate<bool>
do
if upperBound > maxUpperBound then
let message = $"{upperBound} exceeds the maximum upper bound of {maxUpperBound}."
raise (ArgumentOutOfRangeException message)
// Create array and mark 0, 1 as not prime (True).
primeTable[0] <- true
primeTable[1] <- true
// Use Sieve of Eratosthenes to determine prime numbers.
for i = start to float upperBound |> sqrt |> ceil |> int do
if not primeTable[i] then
for multiplier = i to upperBound / i do
if i * multiplier <= upperBound then
primeTable[i * multiplier] <- true
// Populate array with prime number information.
let mutable index = start
while index <> -1 do
index <- Array.FindIndex(primeTable, index, fun flag -> not flag)
if index >= 1 then
primes.Add index
index <- index + 1
member _.GetAllPrimes() =
primes.ToArray()
member _.GetPrimesFrom(prime) =
let start =
Seq.findIndex ((=) prime) primes
if start < 0 then
raise (NotPrimeException(prime, $"{prime} is not a prime number.") )
else
Seq.filter ((>=) prime) primes
|> Seq.toArray
Imports System.Collections.Generic
<Serializable()> Public Class PrimeNumberGenerator
Private Const START As Integer = 2
Private maxUpperBound As Integer = 10000000
Private upperBound As Integer
Private primeTable() As Boolean
Private primes As New List(Of Integer)
Public Sub New(upperBound As Integer)
If upperBound > maxUpperBound Then
Dim message As String = String.Format(
"{0} exceeds the maximum upper bound of {1}.",
upperBound, maxUpperBound)
Throw New ArgumentOutOfRangeException(message)
End If
Me.upperBound = upperBound
' Create array and mark 0, 1 as not prime (True).
ReDim primeTable(upperBound)
primeTable(0) = True
primeTable(1) = True
' Use Sieve of Eratosthenes to determine prime numbers.
For ctr As Integer = START To CInt(Math.Ceiling(Math.Sqrt(upperBound)))
If primeTable(ctr) Then Continue For
For multiplier As Integer = ctr To CInt(upperBound \ ctr)
If ctr * multiplier <= upperBound Then primeTable(ctr * multiplier) = True
Next
Next
' Populate array with prime number information.
Dim index As Integer = START
Do While index <> -1
index = Array.FindIndex(primeTable, index, Function(flag)
Return Not flag
End Function)
If index >= 1 Then
primes.Add(index)
index += 1
End If
Loop
End Sub
Public Function GetAllPrimes() As Integer()
Return primes.ToArray()
End Function
Public Function GetPrimesFrom(prime As Integer) As Integer()
Dim start As Integer = primes.FindIndex(Function(value)
Return value = prime
End Function)
If start < 0 Then
Throw New NotPrimeException(prime, String.Format("{0} is not a prime number.", prime))
Else
Return primes.FindAll(Function(value)
Return value >= prime
End Function).ToArray()
End If
End Function
End Class
Následující příklad provede dvě volání GetPrimesFrom
metody s nečísly, z nichž jedno překročí hranice domény aplikace. V obou případech je výjimka vyvoláná a úspěšně zpracována v kódu klienta.
using System;
using System.Reflection;
class Example
{
public static void Main()
{
int limit = 10000000;
PrimeNumberGenerator primes = new PrimeNumberGenerator(limit);
int start = 1000001;
try
{
int[] values = primes.GetPrimesFrom(start);
Console.WriteLine("There are {0} prime numbers from {1} to {2}",
start, limit);
}
catch (NotPrimeException e)
{
Console.WriteLine("{0} is not prime", e.NonPrime);
Console.WriteLine(e);
Console.WriteLine("--------");
}
AppDomain domain = AppDomain.CreateDomain("Domain2");
PrimeNumberGenerator gen = (PrimeNumberGenerator)domain.CreateInstanceAndUnwrap(
typeof(Example).Assembly.FullName,
"PrimeNumberGenerator", true,
BindingFlags.Default, null,
new object[] { 1000000 }, null, null);
try
{
start = 100;
Console.WriteLine(gen.GetPrimesFrom(start));
}
catch (NotPrimeException e)
{
Console.WriteLine("{0} is not prime", e.NonPrime);
Console.WriteLine(e);
Console.WriteLine("--------");
}
}
}
open System
open System.Reflection
let limit = 10000000
let primes = PrimeNumberGenerator limit
let start = 1000001
try
let values = primes.GetPrimesFrom start
printfn $"There are {values.Length} prime numbers from {start} to {limit}"
with :? NotPrimeException as e ->
printfn $"{e.NonPrime} is not prime"
printfn $"{e}"
printfn "--------"
let domain = AppDomain.CreateDomain "Domain2"
let gen =
domain.CreateInstanceAndUnwrap(
typeof<PrimeNumberGenerator>.Assembly.FullName,
"PrimeNumberGenerator", true,
BindingFlags.Default, null,
[| box 1000000 |], null, null)
:?> PrimeNumberGenerator
try
let start = 100
printfn $"{gen.GetPrimesFrom start}"
with :? NotPrimeException as e ->
printfn $"{e.NonPrime} is not prime"
printfn $"{e}"
printfn "--------"
Imports System.Reflection
Module Example
Sub Main()
Dim limit As Integer = 10000000
Dim primes As New PrimeNumberGenerator(limit)
Dim start As Integer = 1000001
Try
Dim values() As Integer = primes.GetPrimesFrom(start)
Console.WriteLine("There are {0} prime numbers from {1} to {2}",
start, limit)
Catch e As NotPrimeException
Console.WriteLine("{0} is not prime", e.NonPrime)
Console.WriteLine(e)
Console.WriteLine("--------")
End Try
Dim domain As AppDomain = AppDomain.CreateDomain("Domain2")
Dim gen As PrimeNumberGenerator = domain.CreateInstanceAndUnwrap(
GetType(Example).Assembly.FullName,
"PrimeNumberGenerator", True,
BindingFlags.Default, Nothing,
{1000000}, Nothing, Nothing)
Try
start = 100
Console.WriteLine(gen.GetPrimesFrom(start))
Catch e As NotPrimeException
Console.WriteLine("{0} is not prime", e.NonPrime)
Console.WriteLine(e)
Console.WriteLine("--------")
End Try
End Sub
End Module
' The example displays the following output:
' 1000001 is not prime
' NotPrimeException: 1000001 is not a prime number.
' at PrimeNumberGenerator.GetPrimesFrom(Int32 prime)
' at Example.Main()
' --------
' 100 is not prime
' NotPrimeException: 100 is not a prime number.
' at PrimeNumberGenerator.GetPrimesFrom(Int32 prime)
' at Example.Main()
' --------
prostředí Windows Runtime a rozhraní .NET Framework 4.5.1
V .NET pro aplikace Windows 8.x Store pro Windows 8 jsou některé informace o výjimce obvykle ztraceny, když se výjimka šíří prostřednictvím rámců zásobníku non-.NET Framework. Počínaje rozhraním .NET Framework 4.5.1 a Windows 8.1 common language runtime nadále používá původní Exception objekt, který byl vyvolán, pokud nebyla tato výjimka změněna v rámci zásobníku non-.NET Framework.
Konstruktory
Exception() |
Inicializuje novou instanci Exception třídy . |
Exception(SerializationInfo, StreamingContext) |
Zastaralé.
Inicializuje novou instanci třídy Exception se serializovanými daty. |
Exception(String) |
Inicializuje novou instanci Exception třídy se zadanou chybovou zprávou. |
Exception(String, Exception) |
Inicializuje novou instanci Exception třídy se zadanou chybovou zprávou a odkazem na vnitřní výjimku, která je příčinou této výjimky. |
Vlastnosti
Data |
Získá kolekci párů klíč/hodnota, které poskytují další uživatelem definované informace o výjimce. |
HelpLink |
Získá nebo nastaví odkaz na soubor nápovědy přidružený k této výjimce. |
HResult |
Získá nebo nastaví HRESULT, kódovaná číselná hodnota, která je přiřazena ke konkrétní výjimce. |
InnerException |
Exception Získá instanci, která způsobila aktuální výjimku. |
Message |
Získá zprávu, která popisuje aktuální výjimku. |
Source |
Získá nebo nastaví název aplikace nebo objektu, který způsobuje chybu. |
StackTrace |
Získá řetězcovou reprezentaci okamžitých rámců v zásobníku volání. |
TargetSite |
Získá metodu, která vyvolá aktuální výjimku. |
Metody
Equals(Object) |
Určí, zda se zadaný objekt rovná aktuálnímu objektu. (Zděděno od Object) |
GetBaseException() |
Při přepsání v odvozené třídě vrátí hodnotu Exception , která je původní příčinou jedné nebo více následných výjimek. |
GetHashCode() |
Slouží jako výchozí hashovací funkce. (Zděděno od Object) |
GetObjectData(SerializationInfo, StreamingContext) |
Zastaralé.
Při přepsání v odvozené třídě nastaví s SerializationInfo informacemi o výjimce. |
GetType() |
Získá typ modulu runtime aktuální instance. |
GetType() |
Získá aktuální Type instanci. (Zděděno od Object) |
MemberwiseClone() |
Vytvoří mělkou kopii aktuálního Objectsouboru . (Zděděno od Object) |
ToString() |
Vytvoří a vrátí řetězcovou reprezentaci aktuální výjimky. |
Událost
SerializeObjectState |
Zastaralé.
Nastane, když je výjimka serializována k vytvoření objektu stavu výjimky, který obsahuje serializovaná data o výjimce. |
Platí pro
Viz také
Váš názor
Odeslat a zobrazit názory pro