Прескочи до съдържанието
Редактирай

Exceptions

Exceptions (Изключения)

Exceptions в C# сигнализират за грешки по време на изпълнение. Те позволяват отделяне на кода за обработка на грешки от основната бизнес логика.

Основни видове изключения

// Често срещани изключения
ArgumentException           // Невалиден аргумент
ArgumentNullException      // Null аргумент
InvalidOperationException  // Невалидна операция
NullReferenceException    // Опит за достъп до null обект
IndexOutOfRangeException  // Невалиден индекс в масив
FileNotFoundException     // Файлът не е намерен
DivideByZeroException    // Деление на нула
FormatException          // Невалиден формат при конвертиране

Try-Catch-Finally блок

public class ExceptionHandling
{
    public void ProcessFile(string path)
    {
        FileStream file = null;
        try
        {
            file = File.OpenRead(path);
            // Работа с файла
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine($"Файлът не е намерен: {ex.Message}");
        }
        catch (IOException ex)
        {
            Console.WriteLine($"Грешка при четене: {ex.Message}");
        }
        finally
        {
            file?.Dispose(); // Освобождаване на ресурси
        }
    }
}

Хвърляне на изключения

public class BankAccount
{
    private decimal balance;

    public void Withdraw(decimal amount)
    {
        if (amount <= 0)
        {
            throw new ArgumentException("Сумата трябва да е положителна");
        }

        if (amount > balance)
        {
            throw new InvalidOperationException("Недостатъчна наличност");
        }

        balance -= amount;
    }
}

Собствени изключения

public class BusinessException : Exception
{
    public int ErrorCode { get; }

    public BusinessException(string message, int errorCode) 
        : base(message)
    {
        ErrorCode = errorCode;
    }

    public BusinessException(string message, int errorCode, Exception inner) 
        : base(message, inner)
    {
        ErrorCode = errorCode;
    }
}

Exception филтри

public class ExceptionFilters
{
    public void ProcessData(string data)
    {
        try
        {
            // Някаква обработка
        }
        catch (Exception ex) when (ex.Message.Contains("timeout"))
        {
            // Обработка само на timeout грешки
        }
        catch (Exception ex) when (IsRecoverable(ex))
        {
            // Обработка на поправими грешки
        }
    }

    private bool IsRecoverable(Exception ex)
    {
        // Логика за определяне дали грешката е поправима
        return true;
    }
}

Using блок

public class ResourceManagement
{
    public void ProcessFile(string path)
    {
        // Автоматично освобождаване на ресурси
        using (var file = File.OpenRead(path))
        {
            // Работа с файла
        } // Dispose се извиква автоматично
        
        // C# 8.0+ синтаксис
        using var reader = new StreamReader(path);
        // Работа с reader
    } // Dispose се извиква в края на метода
}

Async изключения

public class AsyncExceptions
{
    public async Task ProcessAsync()
    {
        try
        {
            await Task.Delay(1000);
            throw new Exception("Async error");
        }
        catch (Exception ex)
        {
            // Обработка на асинхронни грешки
        }
    }
}

Добри практики

  1. Специфични изключения
// Лошо
throw new Exception("Нещо се обърка");

// Добро
throw new ArgumentException("Невалидна стойност", nameof(parameter));
  1. Прихващане на специфични изключения
// Лошо
try { /* код */ }
catch (Exception ex) { /* всичко */ }

// Добро
try { /* код */ }
catch (FileNotFoundException ex) { /* специфична обработка */ }
catch (IOException ex) { /* специфична обработка */ }
  1. Запазване на stack trace
try
{
    // код
}
catch (Exception ex)
{
    // Запазва оригиналния stack trace
    throw;
    
    // Губи оригиналния stack trace
    // throw ex; // Не правете това!
}
  1. Документиране на изключения
/// <summary>
/// Изтегля файл от сървъра.
/// </summary>
/// <param name="url">URL адрес на файла</param>
/// <exception cref="ArgumentNullException">Когато url е null</exception>
/// <exception cref="WebException">При проблем с мрежата</exception>
public async Task DownloadFileAsync(string url)
{
    if (url == null) throw new ArgumentNullException(nameof(url));
    // Код за изтегляне
}