== Why is this an issue?

The https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/iteration-statements#the-foreach-statement[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 https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist[ArrayList]. The `foreach` statements allow you to downcast elements of a collection of https://learn.microsoft.com/en-us/dotnet/api/system.object[Objects] to any other type. 

The problem is that to achieve the cast, the `foreach` statements silently perform https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/casting-and-type-conversions#explicit-conversions[explicit type conversion], which at runtime can result in an https://learn.microsoft.com/en-us/dotnet/api/system.invalidcastexception[InvalidCastException].

C# code iterating on generic collections or arrays should not rely on `foreach` statement's silent `explicit` conversions.

[source,csharp,diff-id=1,diff-type=noncompliant]
----
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());

    foreach (Orange orange in fruitBasket) // Noncompliant
    {
      //...
    } 
  }
}
----

[source,csharp,diff-id=1,diff-type=compliant]
----
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());

    foreach (Orange orange in fruitBasket.OfType<Orange>())
    {
      //...
    } 
  }
}

----

=== Exceptions

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. 

== Resources

=== Documentation

* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/iteration-statements#the-foreach-statement[Foreach statement]
* https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist[ArrayList]
* https://learn.microsoft.com/en-us/dotnet/api/system.object[Object class]
* https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/casting-and-type-conversions#explicit-conversions[Explicit conversion]
* https://learn.microsoft.com/en-us/dotnet/api/system.invalidcastexception[InvalidCastException]

include::../rspecator.adoc[]