CA2021: Don't call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types
Property | Value |
---|---|
Rule ID | CA2021 |
Title | Don't call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types |
Category | Reliability |
Fix is breaking or non-breaking | Breaking |
Enabled by default in .NET 8 | As warning |
Cause
A call to Enumerable.Cast<TResult>(IEnumerable) or Enumerable.OfType<TResult>(IEnumerable) specifies a type parameter that's incompatible with the type of the input collection.
Rule description
Enumerable.Cast<TResult>(IEnumerable) and Enumerable.OfType<TResult>(IEnumerable) require compatible types to produce the expected result:
- The generic cast used by the sequence returned by Cast<TResult>(IEnumerable) throws an InvalidCastException at run time on elements of incompatible types.
- The generic type check used by OfType<TResult>(IEnumerable) won't succeed with elements of incompatible types, resulting in an empty sequence.
Widening and user-defined conversions aren't supported with generic types.
How to fix violations
Use a compatible type for the type parameter of Cast<TResult>(IEnumerable) and OfType<TResult>(IEnumerable).
Example
The following code snippet shows violations:
var foods = new List<Food>();
// Violation - Food is incompatible with Beverages.
var drinks = Enumerable.Cast<Beverages>(foods);
// Violation - Food is incompatible with Beverages.
var drinks2 = Enumerable.OfType<Beverages>(foods);
class Food { }
class Bread : Food { }
class Beverages { }
' Violation - Integer is incompatible with String.
Dim a1 = (Array.Empty(Of Integer)()).Cast(Of String)
' Violation - Integer is incompatible with String.
Dim a1 = (Array.Empty(Of Integer)()).OfType(Of String)
The following code snippet shows the fixes:
var foods = new List<Food>();
// Bread is compatible with Food.
var breads = Enumerable.Cast<Bread>(foods);
// Bread is compatible with Food.
var breads2 = Enumerable.OfType<Bread>(foods);
class Food { }
class Bread : Food { }
class Beverages { }
' Integer is compatible with Object.
Dim a1 = (Array.Empty(Of Integer)()).Cast(Of Object)
' Integer is compatible with Object.
Dim a1 = (Array.Empty(Of Integer)()).OfType(Of Object)
When to suppress warnings
You shouldn't suppress warnings from this rule, as you'll either encounter run-time exceptions or unexpected behavior (empty sequences).