Skip to content

Commit

Permalink
Modify rule S4039: Improve description to match the implementation (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastien-marichal authored Dec 23, 2024
1 parent bb47c97 commit 07d614d
Showing 1 changed file with 19 additions and 32 deletions.
51 changes: 19 additions & 32 deletions rules/S4039/csharp/rule.adoc
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -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
{
Expand All @@ -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[]

Expand Down

0 comments on commit 07d614d

Please sign in to comment.