rspec/rules/S3217/csharp/rule.adoc

70 lines
2.7 KiB
Plaintext
Raw Normal View History

== 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.
2021-04-28 16:49:39 +02:00
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].
2021-04-28 16:49:39 +02:00
C# code iterating on generic collections or arrays should not rely on `foreach` statement's silent `explicit` conversions.
2021-04-28 16:49:39 +02:00
[source,csharp,diff-id=1,diff-type=noncompliant]
2021-04-28 16:49:39 +02:00
----
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());
2021-04-28 16:49:39 +02:00
foreach (Orange orange in fruitBasket) // Noncompliant
{
//...
2021-04-28 16:49:39 +02:00
}
}
}
----
[source,csharp,diff-id=1,diff-type=compliant]
2021-04-28 16:49:39 +02:00
----
public class Fruit { }
public class Orange : Fruit { }
public class Apple : Fruit { }
class MyTest
2021-04-28 16:49:39 +02:00
{
public void Test()
{
var fruitBasket = new List<Fruit>();
fruitBasket.Add(new Orange());
fruitBasket.Add(new Orange());
fruitBasket.Add(new Apple());
2021-04-28 16:49:39 +02:00
foreach (Orange orange in fruitBasket.OfType<Orange>())
{
//...
}
}
}
2021-04-28 16:49:39 +02:00
----
=== Exceptions
2021-04-28 16:49:39 +02:00
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[]