72 lines
2.0 KiB
Plaintext
72 lines
2.0 KiB
Plaintext
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 ``++Object++``s 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.
|
|
|
|
|
|
== Noncompliant Code Example
|
|
|
|
----
|
|
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
|
|
{
|
|
...
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== Compliant Solution
|
|
|
|
----
|
|
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>())
|
|
{
|
|
...
|
|
}
|
|
----
|
|
|
|
|
|
== Exceptions
|
|
|
|
The rule ignores iterations on collections of ``++object++``s. This includes legacy code that uses ``++ArrayList++``. Furthermore, the rule does not report on cases when user defined conversions are being called.
|
|
|