Подтвердить что ты не робот

Что произойдет, если фильтр фильтра исключений выдает исключение

Я еще не работал на С# 6, но мне было интересно....

Как говорится в заголовке "Что произойдет, если фильтр фильтра" Исключение "выдает исключение?". Я думаю, что действительно ответ: "Фильтр должен быть написан таким образом, чтобы он никогда не выдавал исключение", но, допустим, он это делает. Будет ли это так, как если бы исключение произошло внутри самого catch?

try
{
  throw new Exception("Forced Exception");
}
catch (Exception ex) if (MethodThatThrowsAnException())
{
  WriteLine("Filtered handler 1");
}
catch (Exception ex)
{
  WriteLine("Filtered handler 2");
}

или

try
{
  throw new Exception("Forced Exception");
}
catch (Exception ex) if (MethodThatThrowsAnException())
{
  WriteLine("Filtered handler 1");
}

Изменить: интересный пример Этот раздел был удален из-за ошибки в предполагаемом volatileread, на котором был основан пример. Требуется дальнейшее исследование

4b9b3361

Ответ 1

Если в фильтре есть исключение, то это исключение будет проглочено без фильтра, и фильтр просто завершится неудачей. Это приводит к тому, что исходное исключение идет вниз по случаям catch или в конечном итоге ререйзируется вверх.

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

Вы можете проверить это, используя следующий код на volatileread.coms С# 6 бета-интерпретатор:

public void Main ()
{
    try
    {
        try
        {
            throw new Exception("Original exception");
        }
        catch (Exception ex)
            when (Test()) // `if (Test())` in older previews
        {
            Console.WriteLine("Caught the exception");
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

public static bool Test ()
{
    throw new Exception("Exception in filter condition");
}

В результате появляется "Исходное исключение", появляющееся во внешнем блоке try/catch.


Update

Так как я не понял выход из компилятора volatilereads, когда не использовал внешний блок try/catch, я сам сам установил MS Build Tools 2015 (который на момент ответа по-прежнему использует if, а не when) и попробовал это. Оказывается, что, когда вы не используете внешний try/catch, "исходное исключение" по-прежнему остается тем, что приводит к сбою программы. Таким образом не исключение фильтра. Кажется, это ошибка с компилятором volatiles.

Ответ 2

Вы можете попробовать здесь.

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

Однако, если вы измените второе предложение catch на тип, который не может поймать все, что вы выбрали из вашего метода, ваша программа выйдет из строя из-за необработанного исключения.

Пряная деталь (ошибка): если вы вызываете метод, охватывающий try-catch через отражение, а предложение when генерирует исключение, то это исключение считается необработанным, а не оригинальным. Подробнее здесь.

Ответ 3

Изменить: странность, похоже, вызвана ошибкой в ​​volatileread. Пожалуйста, обратитесь к ответу. Нельзя доверять приведенным ниже экспериментам

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

Проверить с помощью http://volatileread.com/utilitylibrary/snippetcompiler?id=7632

public void Main()
{
  try
  {
    throw new Exception("Forced Exception");
  }
  catch (Exception ex) when (MethodThatThrowsAnException())
  {
    Console.WriteLine("Filtered handler 1");
  }
  catch (Exception ex)
  {
    Console.WriteLine("Filtered handler 2");
  }
}

private bool MethodThatThrowsAnException()
{
  throw new Exception();   
}

Распечатывает "Фильтрованный обработчик 2"

public void Main()
{
  try
  {
    throw new Exception("Forced Exception");
  }
  catch (Exception ex) when (MethodThatThrowsAnException())
  {
    Console.WriteLine("Filtered handler 1");
  }

}

private bool MethodThatThrowsAnException()
{
  throw new Exception("MethodThatThrowsAnException");   
}

Распечатывает:

Необработанная Expecption: System.Exception: MethodThatThrowsAnException
в Program.MethodThatThrowsAnException() в Program.Main()

Еще один интересный вывод для

   public void Main()
    {
      try
      {
        throw new Exception("Forced Exception");
      }
      catch (Exception ex) when(MethodThatThrowsAnException())
      {
        Console.WriteLine("Filtered handler 1");
      }
      catch (Exception ex) when(MethodThatThrowsAnException2())
      {
        Console.WriteLine("Filtered handler 2");

      }
    }

    private bool MethodThatThrowsAnException()
    {
      throw new Exception("MethodThatThrowsAnException");   
    }

    private bool MethodThatThrowsAnException2()
    {
      throw new Exception("MethodThatThrowsAnException2");   
    }

Необработанная Expecption: System.Exception: MethodThatThrowsAnException2 в Program.MethodThatThrowsAnException2() в Program.Main()

Итак, похоже, что он пытается оценить первый улов, если он выдает исключение, которое продолжается до следующего catch. Первый улов, который не прерывается и соответствует всем условиям, затем обрабатывает исключение (BTW - исключение из типа, первоначально поставленного в попытке). Однако, если последний улов, который относится к типу сброшенной ошибки, также генерирует исключение в части фильтра, тогда исключается Необработанное исключение из типа фильтра.

Edit: Примечание:

public void Main()
{
  try
  {
    try
    {
      throw new Exception("Forced Exception");
    }
    catch (Exception ex) when (MethodThatThrowsAnException())
    {
      Console.WriteLine("Filtered handler 1");
    }
  }
  catch (Exception ex)
  {
      Console.WriteLine("Caught");
      Console.WriteLine(ex);
  }
}

private bool MethodThatThrowsAnException()
{
  throw new Exception("MethodThatThrowsAnException");   
}

Выходы:

Пойманный

Исправление System.Exception: принудительное исключение в Program.Main()

Если вы сравните это со вторым выходом... КАК ЭТО ЭТО ВОЗМОЖНО??? Во втором примере выбрано MethodThatThrowsAnException, но в последнем примере поймано "принудительное исключение"

Ответ 4

Исключение, созданное в фильтрах исключений, будет проигнорировано, и это приведет к сбою фильтра.

Исключительные фильтры являются функцией CLR с версии 1.0. Они были доступны с VB.Net F #. Что касается проглатывания/игнорирования исключений в методе фильтрации, это также определенное поведение и вряд ли изменится в последнее время.


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

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

try
{
    throw new Exception("Forced Exception");
}
catch (Exception ex) if (MethodThatThrowsAnException())
{
    WriteLine("Filtered handler 1");
}
catch (IndexOutOfRangeException ex)
{
    WriteLine("Index Out of Range");
}

и метод:

static bool MethodThatThrowsAnException()
{
    throw new IndexOutOfRangeException("Index Out of Range");
}

Хотя метод выбрасывает IndexOutOfRangeException, а в коде вызывающего абонента есть блок catch для этого конкретного исключения, но исключение из метода никогда не сделает его вызывающему. IndexOutOfRangeException из метода фильтра будет проигнорирован, и поскольку исходное исключение throw new Exception("Forced Exception"); из первой строки не обрабатывается нигде, программа выйдет из строя из-за необработанного исключения "Принудительное исключение".


В вашем первом фрагменте кода, поскольку у вас есть блок catch для базы Exception, ваше исходное исключение из первой строки throw new Exception("Forced Exception"); будет обнаружено и обработано там. Вы не заметите исключение, возникшее ранее в методе фильтрации.