From a7df4bebc573a3866b7931e5f828f8b90604ff27 Mon Sep 17 00:00:00 2001 From: Sebastien Marichal Date: Mon, 23 Dec 2024 12:22:46 +0100 Subject: [PATCH] Modify rule S4039: Improve description to match the implementation --- rules/S4039/csharp/rule.adoc | 51 ++++++++++++++---------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/rules/S4039/csharp/rule.adoc b/rules/S4039/csharp/rule.adoc index 65399fb0755..b865c935f7f 100644 --- a/rules/S4039/csharp/rule.adoc +++ b/rules/S4039/csharp/rule.adoc @@ -1,14 +1,22 @@ == Why is this an issue? -When a base type explicitly implements a public interface method, that method is only accessible in derived types through a reference to the current instance (namely ``++this++``). If the derived type explicitly overrides that interface method, the base implementation becomes inaccessible. +When a base type explicitly implements a public interface method, property or event, that member is only accessible in derived types through a reference to the current instance (namely `this`). If the derived type explicitly overrides that interface member, the base implementation becomes inaccessible. +This rule raises an issue when an unsealed, externally visible type provides an explicit member implementation of an `interface` and does not provide an alternate, externally visible member with the same name. -This rule raises an issue when an unsealed, externally visible type provides an explicit method implementation of a ``++public interface++`` and does not provide an alternate, externally visible method with the same name. +=== Exceptions + +This rule does not report a violation for an explicit implementation of `IDisposable.Dispose` when an externally visible `Close()` or `System.IDisposable.Dispose(Boolean)` method is provided. + +== How to fix it +Make the class sealed, change the class member to a non-explicit declaration, or provide a new class member exposing the functionality of the explicit interface member. -=== Noncompliant code example +=== Code examples -[source,csharp] +==== Noncompliant code example + +[source,csharp,diff-id=1,diff-type=noncompliant] ---- public interface IMyInterface { @@ -21,27 +29,13 @@ public class Foo : IMyInterface { MyMethod(); } - - void MyMethod() - { - // Do something ... - } -} - -public class Bar : Foo, IMyInterface -{ - public void MyMethod() - { - // Can't access base.MyMethod() - // ((IMyInterface)this).MyMethod() would be a recursive call - } } ---- -=== Compliant solution +==== Compliant solution -[source,csharp] +[source,csharp,diff-id=1,diff-type=compliant] ---- public interface IMyInterface { @@ -55,26 +49,19 @@ public class Foo : IMyInterface MyMethod(); } - protected void MyMethod() // or public + // This method can be public or protected + protected void MyMethod() { // Do something ... } } - -public class Bar : Foo, IMyInterface -{ - public void MyMethod() - { - // Do something - base.MyMethod(); - } -} ---- +== Resources -=== Exceptions +=== Documentation -This rule does not report a violation for an explicit implementation of ``++IDisposable.Dispose++`` when an externally visible ``++Close()++`` or ``++System.IDisposable.Dispose(Boolean)++`` method is provided. +* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation[Explicit Interface Implementation] ifdef::env-github,rspecator-view[]