CA1033: Interface methods should be callable by child types
TypeName |
InterfaceMethodsShouldBeCallableByChildTypes |
CheckId |
CA1033 |
Category |
Microsoft.Design |
Breaking Change |
Non-breaking |
Cause
An unsealed externally visible type provides an explicit method implementation of a public interface and does not provide an alternative externally visible method that has the same name.
Rule Description
Consider a base type that explicitly implements a public interface method. A type that derives from the base type can access the inherited interface method only through a reference to the current instance (this in C#) that is cast to the interface. If the derived type re-implements (explicitly) the inherited interface method, the base implementation can no longer be accessed. The call through the current instance reference will invoke the derived implementation; this causes recursion and an eventual stack overflow.
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 Violations
To fix a violation of this rule, implement a new method that exposes the same functionality and is visible to derived types or change to a nonexplicit implementation. If a breaking change is acceptable, an alternative is to make the type sealed.
When to Suppress Warnings
It is safe to suppress a warning from this rule if an externally visible method is provided that has the same functionality but a different name than the explicitly implemented method.
Example
The following example shows a type, ViolatingBase, that violates the rule and a type, FixedBase, that shows a fix for the violation.
using System;
namespace DesignLibrary
{
public interface ITest
{
void SomeMethod();
}
public class ViolatingBase: ITest
{
void ITest.SomeMethod()
{
// ...
}
}
public class FixedBase: ITest
{
void ITest.SomeMethod()
{
SomeMethod();
}
protected void SomeMethod()
{
// ...
}
}
sealed public class Derived: FixedBase, ITest
{
public void SomeMethod()
{
// The following would cause recursion and a stack overflow.
// ((ITest)this).SomeMethod();
// The following is unavailable if derived from ViolatingBase.
base.SomeMethod();
}
}
}