2023-06-13 17:09:18 +02:00

70 lines
2.7 KiB
Plaintext

== 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[]