Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NET-912 Modify rule S4039: Improve description to match the implementation #4586

Merged
merged 1 commit into from
Dec 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading