rspec/rules/S3464/csharp/rule.adoc

95 lines
2.0 KiB
Plaintext

== Why is this an issue?
https://en.wikipedia.org/wiki/Recursion[Recursion] is a technique used to define a problem in terms of the problem itself, usually in terms of a simpler version of the problem itself.
For example, the implementation of the generator for the n-th value of the https://en.wikipedia.org/wiki/Fibonacci_sequence[Fibonacci sequence] comes naturally from its mathematical definition, when recursion is used:
[source,csharp]
----
int NthFibonacciNumber(int n)
{
if (n <= 1)
{
return 1;
}
else
{
return NthFibonacciNumber(n - 1) + NthFibonacciNumber(n - 2);
}
}
----
As opposed to:
[source,csharp]
----
int NthFibonacciNumber(int n)
{
int previous = 0;
int last = 1;
for (var i = 0; i < n; i++)
{
(previous, last) = (last, last + previous);
}
return last;
}
----
Use of recursion is acceptable in methods, like the one above, where you can break out of it.
[source,csharp]
----
int NthFibonacciNumber(int n)
{
if (n <= 1)
{
return 1; // Base case: stop the recursion
}
// ...
}
----
It is also acceptable and makes sense in some type definitions:
[source,csharp]
----
class Box : IComparable<Box>
{
public int CompareTo(Box? other)
{
// Compare the two Box instances...
}
}
----
With types, some invalid recursive definitions are caught by the compiler:
[source,csharp]
----
class C2<T> : C2<T> // Error CS0146: Circular base type dependency
{
}
class C2<T> : C2<C2<T>> // Error CS0146: Circular base type dependency
{
}
----
In more complex scenarios, however, the code will compile but execution will result in a https://learn.microsoft.com/en-us/dotnet/api/system.typeloadexception[TypeLoadException] if you try to instantiate the class.
[source,csharp]
----
class C1<T>
{
}
class C2<T> : C1<C2<C2<T>>> // Noncompliant
{
}
var c2 = new C2<int>(); // This would result into a TypeLoadException
----
include::../resources.adoc[]
include::../rspecator.adoc[]