Обработка ошибок wpf

Приложение WPF:

Если Вы знакомы с C# или любым другим языком .NET, который можно использовать с WPF, то обработка исключений не вызовет у Вас больших затруднений: всякий раз, когда у Вас будет часть кода, которая с большой вероятностью может выдать исключение, Вам следует обернуть этот код в блок try-catch и изящно обработать исключение. Взгляните на следующий пример:

private void Button_Click(object sender, RoutedEventArgs e)
{
	string s = null;
	s.Trim();
}

Очевидно, что код в примере написан некорректно. Я пытаюсь исполнить метод Trim() на переменной, которая в текущий момент приняла значение null. Если не обработать исключение, в Вашем приложении произойдет сбой и Windows придется разбираться с данной проблемой. Как вы видите, это не выглядит чересчур уж «user friendly»:

В данном случае, пользователь мог бы форсировать закрытие программы, из-за такой простой и легкообходимой ошибки. Так что, если Вы знаете, о том, что с кодом что-то может пойти не так — используйте блок try-catch таким образом:

private void Button_Click(object sender, RoutedEventArgs e)
{
	string s = null;
	try
	{
		s.Trim();
	}
	catch(Exception ex)
	{
		MessageBox.Show("A handled exception just occurred: " + ex.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
	}
}

Однако, иногда даже простейший код может вызывать исключения, и, вместо того, чтобы оборачивать каждую строчку кода в блок try-catch, можно воспользоваться механизмом WPF, позволяющим глобально обрабатывать исключений. Это становится возможным с использованием события DispatcherUnhandledException в классе Application. Если Вы подписываетесь на это событие, WPF будет вызывать метод этой подписки каждый раз, когда будет появляться исключение, необработанное в Вашем коде. Вот полный пример, основанный на механизме, который мы только что обсудили:

<Window x:Class="WpfTutorialSamples.WPF_Application.ExceptionHandlingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExceptionHandlingSample" Height="200" Width="200">
    <Grid>
        <Button HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click">
            Do something bad!
        </Button>
    </Grid>
</Window>
using System;
using System.Windows;

namespace WpfTutorialSamples.WPF_Application
{
	public partial class ExceptionHandlingSample : Window
	{
		public ExceptionHandlingSample()
		{
			InitializeComponent();
		}

		private void Button_Click(object sender, RoutedEventArgs e)
		{
			string s = null;
			try
			{
				s.Trim();
			}
			catch(Exception ex)
			{
				MessageBox.Show("A handled exception just occurred: " + ex.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
			}
			s.Trim();
		}
	}
}

Обратите внимание, что я дополнительно использовал метод Trim() вне блока try-catch, и исключение появилось на первом вызове, а на втором — нет. Для второго нам необходимо немного магии App.xaml:

<Application x:Class="WpfTutorialSamples.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             DispatcherUnhandledException="Application_DispatcherUnhandledException"
             StartupUri="WPF Application/ExceptionHandlingSample.xaml">
    <Application.Resources>
    </Application.Resources>
</Application>
using System;
using System.Windows;

namespace WpfTutorialSamples
{
	public partial class App : Application
	{
		private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
		{
			MessageBox.Show("An unhandled exception just occurred: " + e.Exception.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Error);
			e.Handled = true;
		}
	}
}

В таком случае обработка исключения выглядит подобным образом как и для локальной обработки, с той лишь разницей, что сообщение об исключении содержит другой текст и изображение. Также, обратите внимание, что я определил свойство e.Handled как true. Это проинформирует WPF о том, что исключение уже обработано и с ним ничего не надо больше делать.

Итог

Обработка исключений — это очень важная часть любого приложения, и, к счастью, WPF и .NET делают этот процес легким, как для локальной, так и для глобальной обработки. Следует обрабатывать исключения локально, когда это необходимо, а глобальную обработку трактуйте как резервный механизм, поскольку локальная обработка позволит Вам управлять проблемой на более глубоком уровне.

This article has been fully translated into the following languages:

  • Chinese

  • Czech

  • Danish

  • Dutch

  • French

  • German

  • Hungarian

  • Italian

  • Japanese

  • Korean

  • Persian

  • Polish

  • Portuguese

  • Romanian

  • Russian

  • Slovak

  • Spanish

  • Turkish

  • Ukrainian

  • Vietnamese

Is your preferred language not on the list? Click here to help us translate this article into your language!


We have a WPF application where parts of it may throw exceptions at runtime. I’d like to globally catch any unhandled exceptions and log them, but otherwise continue program execution as if nothing happened (kinda like VB’s On Error Resume Next).

Is this possible in C#? And if so, where exactly would I need to put the exception handling code?

Currently I can’t see any single point where I could wrap a try/catch around and which would catch all exceptions that could occur. Even then, I would have left whatever has been executed because of the catch. Or am I thinking in horribly wrong directions here?

ETA: Because many people below pointed it out: The application is not for controlling nuclear power plants. If it crashes, it’s not that big a deal, but it throws random exceptions that are mostly UI-related that are a nuisance in the context where it would be used. There were (and probably still are) a few of those and since it uses a plugin architecture and may be extended by others (also students in that case; so no experienced developers that are able to write completely error-free code).

As for the exceptions that get caught: I do log them to a log file, including the complete stack trace. That was the whole point of that exercise. Just to counter those people that were taking my analogy to VB’s OERN too literally.

I know that blindly ignoring certain classes of errors is dangerous and might corrupt my application instance. As said before, this program isn’t mission-critical for anyone. No-one in their right mind would bet the survival of the human civilization on it. It’s simply a little tool for testing certain design approaches wrt. software engineering.

For the immediate use of the application there are not many things that can happen on an exception:

  • No exception handling – error dialog and application exit. Experiment has to be repeated, though likely with another subject. No errors have been logged, which is unfortunate.
  • Generic exception handling – benign error trapped, no harm done. This should be the common case judged from all errors we were seeing during development. Ignoring this kind of errors should have no immediate consequences; the core data structures are tested well enough that they will easily survive this.
  • Generic exception handling – serious error trapped, possibly crash at a later point. This may happen rarely. We’ve never seen it so far. The error is logged anyway and a crash might be inevitable. So this is conceptually similar to the very first case, except that we have a stack trace. And in the majority of cases the user won’t even notice.

As for the experiment data generated by the program: A serious error would at worst just cause no data to be recorded. Subtle changes that change the result of the experiment ever so slightly are pretty unlikely. And even in that case, if the results seem dubious the error was logged; one can still throw away that data point if it’s a total outlier.

To summarize: Yes, I consider myself still at least partially sane and I don’t consider a global exception handling routine which leaves the program running to be necessarily totally evil. As said twice before, such a decision might be valid, depending on the application. In this case it was judged a valid decision and not total and utter bullshit. For any other application that decision might look different. But please don’t accuse me or the other people who worked on that project to potentially blow up the world just because we’re ignoring errors.

Side note: There is exactly one user for that application. It’s not something like Windows or Office that gets used by millions where the cost of having exceptions bubble to the user at all would be very different in the first place already.

Валидация данных

Последнее обновление: 31.10.2015

При работе с данными важную роль играет валидация данных. Прежде чем использовать полученные от пользователя данные, нам надо убедиться,
что они введены правильно и представляют корректные значения. Один из встроенных способов проверки введенных данных в WPF представлен классом
ExceptionValidationRule. Этот класс обозначает введенные данные как некорректные, если в процессе ввода возникает какое-либо исключение,
например, исключение преобразования типов.

Итак, допустим, у нас определен следующий класс:

    public class PersonModel
    {
        public string Name { get; set; }
        public int Age { get;set;}
        public string Position { get; set; }
    }

Этот класс представляет человека и предполагает три свойства: имя, возраст и должность. Понятно, что возраст должен представлять числовое значение.
Однако пользователи могут ввести что угодно. Мы можем обрабатывать ввод с клавиатуры, а можем воспользоваться классом ExceptionValidationRule,
который в случае неудачи преобразования строки в число установит красную границу вокруг текстового поля.

Сначала создадим в файле кода объект нашего класса PersonModel и установим контекст данных окна:

public partial class MainWindow : Window
{
    PersonModel Tom;
    public MainWindow()
    {
        InitializeComponent();
        Tom=new PersonModel();
        this.DataContext = Tom;
    } 
}

Теперь установим привязку в xaml-коде:

<Window x:Class="DataValidationApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataValidationApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="1" Height="30" Margin="0 0 15 0"/>
        
        <TextBox Grid.Column="1" Grid.Row="1" Height="30"  Margin="0 0 15 0">
            <TextBox.Text>
                <Binding Path="Age">
                    <Binding.ValidationRules>
                        <ExceptionValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        
        <TextBox Grid.Column="1" Grid.Row="2" Height="30" Margin="0 0 15 0" />
        <Label Content="Введите имя" Height="30" />
        <Label Grid.Row="1" Content="Введите возраст" Height="30" />
        <Label Grid.Row="2" Content="Введите должность" Height="30" />
    </Grid>
</Window>

В данном случае мы задаем объект Binding для свойства Text. Данный объект имеет коллекцию правил валидации вводимых данных — ValidationRules.
Эта коллекция принимает только одно правило валидации, представленное классом ExceptionValidationRule. Запустим приложение на выполнение
и попробуем ввести в текстовое поле какое-нибудь нечисловое значение. В этом случае текстовое поле будет обведено красным цветом, указывая на то,
что в вводимых данных имеются ошибки.

Валидация данных в WPF

Мы также можем реализовать свою логику валидации для класса модели. Для этого модель должна реализовать интерфейс IDataErrorInfo. Этот интерфейс
имеет следующий синтаксис:

public interface IDataErrorInfo
{
	string Error {get;}
    string this[string columnName] { get;}
}

Допустим, мы хотим ограничить возраст человека только положительными значениями от 0 до 100. Тогда валидация модели будет выглядеть следующим образом:

public class PersonModel : IDataErrorInfo
{
    public string Name { get; set; }
    public int Age {get;set;}
    public string Position { get; set; }
    public string this[string columnName]
    {
        get
        {
            string error=String.Empty;
            switch (columnName)
            {
                case "Age" :
					if ((Age < 0) || (Age > 100))
					{
						error = "Возраст должен быть больше 0 и меньше 100";
					}
					break;
                case "Name" :
                    //Обработка ошибок для свойства Name
                    break;
                case "Position" :
                    //Обработка ошибок для свойства Position
                    break;
            }
            return error;
        }
    }
    public string Error
    {
        get { throw new NotImplementedException(); }
    }
}

И последнее — нам осталось немного подкорректировать xaml-код. Теперь нам надо использовать в качестве правила валидации класс
DataErrorValidationRule:

<TextBox Grid.Column="1" Grid.Row="1" Height="30"  Margin="0 0 15 0">
    <TextBox.Text>
        <Binding Path="Age">
            <Binding.ValidationRules>
                <DataErrorValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Так как число 450 больше 100 и поэтому не является валидным, то текстовое поле выделяется красным.

Настройка внешнего вида при ошибке валидации

Но это еще не все. Мы можем сами управлять через шаблоны отображением ошибки ввода. В предыдущем случае у нас граница текстового поля при ошибке
окрашивалась в красный цвет. Попробуем настроить данное действие. Для этого нам нужно использовать элемент AdornedElementPlaceholder.
Итак изменим разметку приложения следующим образом, добавив в нее шаблон элемента управления:

<Window x:Class="DataValidationApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataValidationApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="validationFailed">
            <StackPanel Orientation="Horizontal">
                <Border BorderBrush="Violet" BorderThickness="2">
                    <AdornedElementPlaceholder />
                </Border>
                <TextBlock Foreground="Red" FontSize="26" FontWeight="Bold">!</TextBlock>
            </StackPanel>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="1" Height="30" Margin="0 0 15 0"/>
        
        <TextBox Grid.Column="1" Grid.Row="1" Height="30"  Margin="0 0 15 0" 
			Validation.ErrorTemplate="{StaticResource validationFailed}" >
            <TextBox.Text>
                <Binding Path="Age">
                    <Binding.ValidationRules>
                        <DataErrorValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        
        <TextBox Grid.Column="1" Grid.Row="2" Height="30" Margin="0 0 15 0" />
        <Label Content="Введите имя" Height="30" />
        <Label Grid.Row="1" Content="Введите возраст" Height="30" />
        <Label Grid.Row="2" Content="Введите должность" Height="30" />
    </Grid>
</Window>

С помощью свойства Validation.ErrorTemplate мы получаем шаблон, который будет отрабатывать при ошибке валидации.
Этот шаблон, определенный выше в ресурсах окна, определяет границу фиолетового цвета вокруг элемента ввода, а также отображает рядом с ним
восклицательный знак красного цвета. Запустим приложение и попробуем ввести в текстовое поле какое-нибудь некорректное значение. В результате сработает наш шаблон:

Настройка валидации в WPF

Мы также можем определить поведение и визуализацию через триггер при установке свойства Validation.HasError в True. А с помощью свойства
ToolTip можно создать привязку к сообщению ошибки:

<Style TargetType="TextBox">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="ToolTip" 
                Value="{Binding RelativeSource={RelativeSource Self},
                    Path=(Validation.Errors)[0].ErrorContent}" />
            <Setter Property="Foreground" Value="Red" />
        </Trigger>
    </Style.Triggers>
</Style>

Всплывающая подсказка при валидации в WPF

Обработка событий валидации

WPF предоставляет механизм обработки ошибки валидации с помощью события Validation.Error. Данное событие можно использовать в любом элементе управления.
Например, пусть при ошибке валидации при вводе в текстовое поле выскакивает сообщение с ошибкой. Для этого изменим текстовое поле следующим образом:

<TextBox Grid.Column="1" Grid.Row="1" Height="30"  Margin="0 0 15 0" Validation.Error="TextBox_Error">
    <TextBox.Text>
        <Binding Path="Age" NotifyOnValidationError="True">
            <Binding.ValidationRules>
                <DataErrorValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Здесь, во-первых, надо отметить установку свойства NotifyOnValidationError="True":

<Binding Path="Age" NotifyOnValidationError="True">

Это позволит вызывать событие валидации.

И также устанавливается сам обработчик события валидации:

<TextBox Grid.Column="1" Grid.Row="1" Height="30"  Margin="0 0 15 0" 
	Validation.Error="TextBox_Error">

При этом следует отметить, что событие Validation.Error является поднимающимся (bubbling events), поэтому мы можем установить для него обработчик и в контейнере Grid или в любых других контейнерах,
в которых находится это текстовое поле. И в случае ошибки событие также будет генерироваться и обрабатываться.

И в конце определим в файле кода c# сам обработчик:

private void TextBox_Error(object sender, ValidationErrorEventArgs e)
{
    MessageBox.Show(e.Error.ErrorContent.ToString());
}


An exception is any error condition or an unexpected behavior that is encountered during the execution of a program. Exceptions can be raised due to many reasons, some of them are as follows −

  • Fault in your code or in code that you call (such as a shared library),

  • Unavailable operating system resources,

  • Unexpected conditions that a common language runtime encounters (such as code that cannot be verified)

Syntax

Exceptions have the ability to transfer the flow of a program from one part to another. In .NET framework, exception handling has the following four keywords −

  • try − In this block, the program identifies a certain condition which raises some exception.

  • catch − The catch keyword indicates the catching of an exception. A try block is followed by one or more catch blocks to catch an exception with an exception handler at the place in a program where you want to handle the problem.

  • finally − The finally block is used to execute a given set of statements, whether an exception is thrown or not thrown. For example, if you open a file, it must be closed whether an exception is raised or not.

  • throw − A program throws an exception when a problem shows up. This is done using a throw keyword.

The syntax to use these four keywords goes as follows −

try { 
   ///This will still trigger the exception 
} 
catch (ExceptionClassName e) { 
   // error handling code 
} 
catch (ExceptionClassName e) { 
   // error handling code
}
catch (ExceptionClassName e) { 
   // error handling code 
} 
finally { 
   // statements to be executed 
}

Multiple catch statements are used in those cases where a try block can raise more than one exception depending on the situation of a program flow.

Hierarchy

Almost all the exception classes in the .NET framework are directly or indirectly derived from the Exception class. The most important exception classes derived from the Exception class are −

  • ApplicationException class − It supports exceptions which are generated by programs. When developer want to define exception then class should be derived from this class.

  • SystemException class − It is the base class for all predefined runtime system exceptions. The following hierarchy shows the standard exceptions provided by the runtime.

Hierarchy

The following table lists the standard exceptions provided by the runtime and the conditions under which you should create a derived class.

Exception type Base type Description
Exception Object Base class for all exceptions.
SystemException Exception Base class for all runtime-generated errors.
IndexOutOfRangeException SystemException Thrown by the runtime only when an array is indexed improperly.
NullReferenceException SystemException Thrown by the runtime only when a null object is referenced.
AccessViolationException SystemException Thrown by the runtime only when invalid memory is accessed.
InvalidOperationException SystemException Thrown by methods when in an invalid state.
ArgumentException SystemException Base class for all argument exceptions.
ArgumentNullException ArgumentException Thrown by methods that do not allow an argument to be null.
ArgumentOutOfRangeException ArgumentException Thrown by methods that verify that arguments are in a given range.
ExternalException SystemException Base class for exceptions that occur or are targeted at environments outside the runtime.
SEHException ExternalException Exception encapsulating Win32 structured exception handling information.

Example

Let’s take a simple example to understand the concept better. Start by creating a new WPF project with the name WPFExceptionHandling.

Drag one textbox from the toolbox to the design window. The following XAML code creates a textbox and initializes it with some properties.

<Window x:Class = "WPFExceptionHandling.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFExceptionHandling"
   mc:Ignorable = "d" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid> 
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"
         Height = "241" Margin = "70,39,0,0" TextWrapping = "Wrap" 
         VerticalAlignment = "Top" Width = "453"/> 
   </Grid> 
	
</Window>

Here is the file reading with exception handling in C#.

using System; 
using System.IO; 
using System.Windows;

namespace WPFExceptionHandling { 

   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
         ReadFile(0); 
      }
		
      void ReadFile(int index) { 
         string path = @"D:Test.txt"; 
         StreamReader file = new StreamReader(path); 
         char[] buffer = new char[80]; 
			
         try { 
            file.ReadBlock(buffer, index, buffer.Length); 
            string str = new string(buffer); 
            str.Trim(); 
            textBox.Text = str; 
         }
         catch (Exception e) {
            MessageBox.Show("Error reading from "+ path + "nMessage = "+ e.Message);
         } 
         finally { 
            if (file != null) { 
               file.Close(); 
            } 
         } 
      } 
   } 
}

When you compile and execute the above code, it will produce the following window in which a text is displayed inside the textbox.

Exceptional Handling Output

When there is an exception raised or you throw it manually (as in the following code), then it will show a message box with error.

using System; 
using System.IO; 
using System.Windows;

namespace WPFExceptionHandling {
 
   public partial class MainWindow : Window {
	
      public MainWindow() { 
         InitializeComponent(); 
         ReadFile(0); 
      } 
		
      void ReadFile(int index) { 
         string path = @"D:Test.txt"; 
         StreamReader file = new StreamReader(path); 
         char[] buffer = new char[80]; 
			
         try { 
            file.ReadBlock(buffer, index, buffer.Length); 
            string str = new string(buffer); 
            throw new Exception(); 
            str.Trim(); 
            textBox.Text = str; 
         }
         catch (Exception e) { 
            MessageBox.Show("Error reading from "+ path + "nMessage = "+ e.Message); 
         } 
         finally { 
            if (file != null) { 
               file.Close(); 
            } 
         } 
      } 
   } 
}

When an exception is raised while executing the above code, it will display the following message.

Exception Message

We recommend that you execute the above code and experiment with its features.

Исключением является любое состояние ошибки или непредвиденное поведение, возникающее во время выполнения программы. Исключения могут быть вызваны по многим причинам, некоторые из них следующие:

  • Ошибка в вашем коде или в коде, который вы вызываете (например, в общей библиотеке),

  • Недоступные ресурсы операционной системы,

  • Неожиданные условия, с которыми сталкивается общеязыковая среда выполнения (например, код, который невозможно проверить)

Ошибка в вашем коде или в коде, который вы вызываете (например, в общей библиотеке),

Недоступные ресурсы операционной системы,

Неожиданные условия, с которыми сталкивается общеязыковая среда выполнения (например, код, который невозможно проверить)

Синтаксис

Исключения имеют возможность переносить поток программы из одной части в другую. В .NET Framework обработка исключений имеет следующие четыре ключевых слова:

  • try – в этом блоке программа идентифицирует определенное условие, которое вызывает некоторое исключение.

  • catch – ключевое слово catch указывает на перехват исключения. За блоком try следует один или несколько блоков catch, чтобы перехватить исключение с помощью обработчика исключений в том месте программы, где вы хотите решить проблему.

  • finally – блок finally используется для выполнения заданного набора операторов независимо от того, было ли выброшено исключение или нет. Например, если вы открываете файл, он должен быть закрыт независимо от того, возбуждено ли исключение или нет.

  • throw – программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова throw.

try – в этом блоке программа идентифицирует определенное условие, которое вызывает некоторое исключение.

catch – ключевое слово catch указывает на перехват исключения. За блоком try следует один или несколько блоков catch, чтобы перехватить исключение с помощью обработчика исключений в том месте программы, где вы хотите решить проблему.

finally – блок finally используется для выполнения заданного набора операторов независимо от того, было ли выброшено исключение или нет. Например, если вы открываете файл, он должен быть закрыт независимо от того, возбуждено ли исключение или нет.

throw – программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова throw.

Синтаксис для использования этих четырех ключевых слов выглядит следующим образом:

try { 
   ///This will still trigger the exception 
} 
catch (ExceptionClassName e) { 
   // error handling code 
} 
catch (ExceptionClassName e) { 
   // error handling code
}
catch (ExceptionClassName e) { 
   // error handling code 
} 
finally { 
   // statements to be executed 
}

Несколько операторов catch используются в тех случаях, когда блок try может вызвать более одного исключения в зависимости от ситуации потока программы.

иерархия

Почти все классы исключений в .NET Framework прямо или косвенно являются производными от класса Exception. Наиболее важные классы исключений, полученные из класса Exception, –

  • Класс ApplicationException – он поддерживает исключения, которые генерируются программами. Когда разработчик хочет определить исключение, класс должен быть производным от этого класса.

  • Класс SystemException – это базовый класс для всех предопределенных системных исключений времени выполнения. В следующей иерархии показаны стандартные исключения, предоставляемые средой выполнения.

Класс ApplicationException – он поддерживает исключения, которые генерируются программами. Когда разработчик хочет определить исключение, класс должен быть производным от этого класса.

Класс SystemException – это базовый класс для всех предопределенных системных исключений времени выполнения. В следующей иерархии показаны стандартные исключения, предоставляемые средой выполнения.

иерархия

В следующей таблице перечислены стандартные исключения, предоставляемые средой выполнения, и условия, при которых вы должны создать производный класс.

Тип исключения Базовый тип Описание
исключение объект Базовый класс для всех исключений.
SystemException исключение Базовый класс для всех ошибок во время выполнения.
IndexOutOfRangeException SystemException Бросается средой выполнения только тогда, когда массив проиндексирован неправильно.
NullReferenceException SystemException Брошенный средой выполнения только когда ссылка на нулевой объект.
AccessViolationException SystemException Выбрасывается средой выполнения только при обращении к недействительной памяти.
InvalidOperationException SystemException Брошенный методами, когда в недопустимом состоянии.
ArgumentException SystemException Базовый класс для всех исключений аргументов.
ArgumentNullException ArgumentException Вызывается методами, которые не позволяют аргументу быть нулевым.
ArgumentOutOfRangeException ArgumentException Вызывается методами, которые проверяют, что аргументы находятся в заданном диапазоне.
Внешнее исключение SystemException Базовый класс для исключений, которые возникают или нацелены на среды вне среды выполнения.
SEHException Внешнее исключение Исключение, инкапсулирующее Win32 структурированную информацию обработки исключений.

пример

Давайте рассмотрим простой пример, чтобы лучше понять концепцию. Начните с создания нового проекта WPF с именем WPFExceptionHandling .

Перетащите одно текстовое поле с панели инструментов в окно дизайна. Следующий код XAML создает текстовое поле и инициализирует его с некоторыми свойствами.

<Window x:Class = "WPFExceptionHandling.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFExceptionHandling"
   mc:Ignorable = "d" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid> 
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"
         Height = "241" Margin = "70,39,0,0" TextWrapping = "Wrap" 
         VerticalAlignment = "Top" Width = "453"/> 
   </Grid> 
	
</Window>

Вот чтение файла с обработкой исключений в C #.

using System; 
using System.IO; 
using System.Windows;

namespace WPFExceptionHandling { 

   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
         ReadFile(0); 
      }
		
      void ReadFile(int index) { 
         string path = @"D:Test.txt"; 
         StreamReader file = new StreamReader(path); 
         char[] buffer = new char[80]; 
			
         try { 
            file.ReadBlock(buffer, index, buffer.Length); 
            string str = new string(buffer); 
            str.Trim(); 
            textBox.Text = str; 
         }
         catch (Exception e) {
            MessageBox.Show("Error reading from "+ path + "nMessage = "+ e.Message);
         } 
         finally { 
            if (file != null) { 
               file.Close(); 
            } 
         } 
      } 
   } 
}

Когда вы скомпилируете и выполните приведенный выше код, он создаст следующее окно, в котором текст отображается внутри текстового поля.

Исключительный результат обработки

Когда возникает исключение или вы его выбрасываете вручную (как в следующем коде), тогда появится сообщение с ошибкой.

using System; 
using System.IO; 
using System.Windows;

namespace WPFExceptionHandling {
 
   public partial class MainWindow : Window {
	
      public MainWindow() { 
         InitializeComponent(); 
         ReadFile(0); 
      } 
		
      void ReadFile(int index) { 
         string path = @"D:Test.txt"; 
         StreamReader file = new StreamReader(path); 
         char[] buffer = new char[80]; 
			
         try { 
            file.ReadBlock(buffer, index, buffer.Length); 
            string str = new string(buffer); 
            throw new Exception(); 
            str.Trim(); 
            textBox.Text = str; 
         }
         catch (Exception e) { 
            MessageBox.Show("Error reading from "+ path + "nMessage = "+ e.Message); 
         } 
         finally { 
            if (file != null) { 
               file.Close(); 
            } 
         } 
      } 
   } 
}

Если во время выполнения вышеуказанного кода возникнет исключение, будет отображено следующее сообщение.

Сообщение об исключении

Мы рекомендуем вам выполнить приведенный выше код и поэкспериментировать с его функциями.

Понравилась статья? Поделить с друзьями:
  • Обработка ошибок windows forms
  • Обработка ошибок mysql php
  • Обработка ошибок visual basic
  • Обработка ошибок matlab
  • Обработка ошибок vba outlook