rspec/rules/S4019/csharp/rule.adoc

73 lines
2.8 KiB
Plaintext
Raw Normal View History

== Why is this an issue?
2023-06-13 09:45:25 +02:00
When a method in a derived class has:
2021-04-28 16:49:39 +02:00
2023-06-13 09:45:25 +02:00
* the same name as a method in the base class
* but types of parameters that are ancestors (for example `string` in the base class and `object` in the derived class)
2023-06-13 09:45:25 +02:00
the result is that the base method becomes hidden.
2021-04-28 16:49:39 +02:00
2023-06-13 09:45:25 +02:00
As shown in the following code snippet, when an instance of the derived class is used, invoking the method with an argument that matches the less derived parameter type will invoke the derived class method instead of the base class method:
[source,csharp,diff-id=1,diff-type=noncompliant]
2021-04-28 16:49:39 +02:00
----
2023-06-13 09:45:25 +02:00
class BaseClass
{
internal void MyMethod(string str) => Console.WriteLine("BaseClass: Method(string)");
}
2021-04-28 16:49:39 +02:00
2023-06-13 09:45:25 +02:00
class DerivedClass : BaseClass
2021-04-28 16:49:39 +02:00
{
2023-06-13 09:45:25 +02:00
internal void MyMethod(object str) => Console.WriteLine("DerivedClass: Method(object)"); // Noncompliant
2021-04-28 16:49:39 +02:00
}
2023-06-13 09:45:25 +02:00
// ...
BaseClass baseObj = new BaseClass();
baseObj.MyMethod("Hello"); // Output: BaseClass: Method(string)
2023-06-13 09:45:25 +02:00
DerivedClass derivedObj = new DerivedClass();
derivedObj.MyMethod("Hello"); // Output: DerivedClass: Method(object) - DerivedClass method is hiding the BaseClass method
2021-04-28 16:49:39 +02:00
2023-06-13 09:45:25 +02:00
BaseClass derivedAsBase = new DerivedClass();
derivedAsBase.MyMethod("Hello"); // Output: BaseClass: Method(string)
2021-04-28 16:49:39 +02:00
----
2023-06-13 09:45:25 +02:00
[source,csharp,diff-id=1,diff-type=compliant]
----
class BaseClass
2021-04-28 16:49:39 +02:00
{
2023-06-13 09:45:25 +02:00
internal void MyMethod(string str) => Console.WriteLine("BaseClass: Method(string)");
2021-04-28 16:49:39 +02:00
}
2023-06-13 09:45:25 +02:00
class DerivedClass : BaseClass
{
internal void MyOtherMethod(object str) => Console.WriteLine("DerivedClass: Method(object)"); // Compliant
}
// ...
BaseClass baseObj = new BaseClass();
baseObj.MyMethod("Hello"); // Output: BaseClass: Method(string)
2023-06-13 09:45:25 +02:00
DerivedClass derivedObj = new DerivedClass();
derivedObj.MyMethod("Hello"); // Output: BaseClass: Method(string)
BaseClass derivedAsBase = new DerivedClass();
derivedAsBase.MyMethod("Hello"); // Output: BaseClass: Method(string)
----
2023-06-13 09:45:25 +02:00
Keep in mind that you cannot fix this issue by using the https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/new-modifier[new keyword] or by marking the method in the base class as `virtual` and overriding it in the `DerivedClass` because the parameter types are different.
2023-06-13 09:45:25 +02:00
=== Exceptions
2023-06-13 09:45:25 +02:00
The rule is not raised when the two methods have the same parameter types.
2023-06-13 09:45:25 +02:00
== Resources
2023-06-13 09:45:25 +02:00
=== Documentation
2023-06-13 09:45:25 +02:00
* https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords[Knowing When to Use Override and New Keywords]
* https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/member-overloading[Member overloading]
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/new-modifier['new' modifier]
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0108[CS0108 - Hiding inherited member]
2023-06-13 09:45:25 +02:00
include::../rspecator.adoc[]