The foreach statement was introduced in the C# language prior to generics to make it easier to work with the non-generic collections
available at that time such as ArrayList. The foreach statements allows you to downcast elements of a collection of
Objects to any other type. The problem is that to achieve the cast, the foreach statements silently performs
explicit type conversion, which at runtime can result in an InvalidCastException.
C# code iterating on generic collections or arrays should not rely on foreach statement’s silent explicit
conversions.
public class Fruit { }
public class Orange : Fruit { }
public class Apple : Fruit { }
class MyTest
{
public void Test()
{
var fruitBasket = new List<Fruit>();
fruitBasket.Add(new Orange());
fruitBasket.Add(new Orange());
// fruitBasket.Add(new Apple()); // uncommenting this line will make both foreach below throw an InvalidCastException
foreach (Fruit fruit in fruitBasket)
{
var orange = (Orange)fruit; // This "explicit" conversion is hidden within the foreach loop below
...
}
foreach (Orange orange in fruitBasket) // Noncompliant
{
...
}
}
}
var fruitBasket = new List<Orange>();
fruitBasket.Add(new Orange());
fruitBasket.Add(new Orange());
// fruitBasket.Add(new Apple()); // uncommenting this line won't compile
foreach (Orange orange in fruitBasket)
{
...
}
or
var fruitBasket = new List<Fruit>();
fruitBasket.Add(new Orange());
fruitBasket.Add(new Orange());
fruitBasket.Add(new Apple());
foreach (Orange orange in fruitBasket.OfType<Orange>())
{
...
}
The rule ignores iterations on collections of objects. This includes legacy code that uses ArrayList. Furthermore, the
rule does not report on cases when user defined conversions are being called.