Do not raise exceptions in filter blocks

TypeName

DoNotRaiseExceptionsInFilterBlocks

CheckId

CA2219

Category

Microsoft.Usage

Breaking Change

NonBreaking

Cause

A method contains a filtered exception handler, and the filter raises exceptions.

Rule Description

When an exception filter raises an exception, the exception is caught by the common language runtime, and the filter returns false. This behavior is indistinguishable from the filter executing and returning false intentionally.

Currently, Visual Basic .NET and the Visual C++ support exception filters.

How to Fix Violations

To fix a violation of this rule, do not raise exceptions in an exception filter.

When to Exclude Warnings

Do not exclude a warning from this rule. There are no scenarios under which an exception raised by an exception filter provides a benefit to the executing code.

Example

The following example shows a type that violates this rule. Note that the filter appears to return false when it throws an exception.

Imports System
Module ExceptionFilter
Public Class FilterTest
   
   ' The following function is used as an exception filter.
   ' Violates rule: DoNotRaiseExceptionsInFilterBlocks.
   Public Function AlwaysTrueFilter(label as String) as Boolean
       Console.WriteLine("In filter for {0}.", label)
       ' The following exception terminates the filter.
       ' The common language runtime does not return the exception to the user.
       Throw New ApplicationException("Filter generated exception.")
       Return True
   End Function
   
   Public Sub ThrowException()
   Try
      Throw New ApplicationException("First exception.")

      ' Because the filter throws an exception, this catch clause fails to catch the exception.
      Catch e as ApplicationException When Not AlwaysTrueFilter("First")
            Console.WriteLine("Catching first filtered ApplicationException {0}", e)
            
      ' Because the previous catch fails, this catch handles the exception.
      Catch e as ApplicationException 
      Console.WriteLine("Catching any ApplicationException - {0}", e.Message)
      
    End Try 
    
    ' The behavior is the same when the filter test is reversed.
    Try   
      Throw New ApplicationException("Second exception.")
 
      ' Change the filter test from When Not to When.
      
      ' This catch fails.
      Catch e as ApplicationException When AlwaysTrueFilter("Second")
            Console.WriteLine("Catching second filtered ApplicationException {0}", e)
            
      ' This catch handles the exception.
      Catch e as ApplicationException 
      Console.WriteLine("Catching any ApplicationException - {0}", e.Message)
   End Try  
   End Sub 
   
End Class 
Sub  Main()
        Dim  test as FilterTest = New FilterTest()
        
        test.ThrowException()
   End Sub
End Module

The example produces the following output.

Output

In filter for First.
Catching any ApplicationException - First exception.
In filter for Second.
Catching any ApplicationException - Second exception.