Share via


Design Guideline Update: Explicit Member Implementation

Long overdue update the the guidelines on Explicit member implementation.
As always, feedback welcome.


Explicit
Member  Implementation

Explicit member implementation allows an interface member to be implemented
such that it is only available when cast to the interface type.  For example consider the following
definition:

public struct Int32 : IConvertible, IComparable
{
public override string
ToString () {..}
int
ICovertible.ToInt32 () {..}

...
}

This code calls the IConvertable members:

int i = 42;
i.ToString(); // works
i.ToInt32(); // does not
compile
((IConvertible) i).ToInt32();
// works

           
Do not use explicit
members as a security boundary. They can be called by any client who cast an
instance to the interface.

*
Do use explicit
members to hide implementation details

*
Do use explicit members to
approximate private interface implementations. If you need to implement an interface
for only infrastructure reasons and you NEVER expect developers to directly call
methods on that interface from this type then implement the members explicitly
to “hide” them from public view.
For example, all of the base datatypes must
implement IConvertable for infrastructure reasons. IConvertable has 19 conversion methods
that would pollute the public interface of these types. So it is appropriate to explicitly
implement these members so they are available when cast to IConvertable but do
not appear on the public interfaces.
This makes the development experience much
cleaner.

*
Do expose an
alternative way to access any explicitly implemented members that subclasses are
allowed to override.[1]  Use the
same method name unless a conflict would arise.

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();
        }
 
        virtual
protected void SomeMethod()
        {
            // ...
        }
    }
    public
class Derived : FixedBase, ITest
    {
     override
protected void SomeMethod()
        {
            // ...
            base.SomeMethod();

             // This would cause recursion and a stack
            // overflow.
            // ((ITest)this).SomeMethod();
        }
    }
}

[1] Fully Covered by ExplicitMethodImplementationsInUnsealedClassesHaveVisibleAlternates

Comments

  • Anonymous
    November 15, 2003
    The comment has been removed
  • Anonymous
    November 15, 2003
    Is the fact that subclasses can't override a method of a privately implemented interface by design? Are there any plans for C#/Whidbey to allow this? It would be very useful at times, and make privately implemented interfaces more appealing.
  • Anonymous
    November 15, 2003
    The comment has been removed
  • Anonymous
    November 15, 2003
    The comment has been removed
  • Anonymous
    November 16, 2003
    The comment has been removed
  • Anonymous
    November 16, 2003
    Brad - bummer that private interface overriding isn't being looked at. I just ran into it again. I'm creating a collection using NameObjectCollectionBase as the base class, and since it overrides GetEnumerator privately, I can't provide my own enumerator class (and, incidentally, it enumerates keys rather than values - odd choice). CollectionBase seems to have the same problem. Ah, but then generics will resolve these issues anyway. Whidbey, take me away. :)
  • Anonymous
    November 16, 2003
    Brad - oops I just found out how to implement a custom enumerator on a CollectionBase-derived class. Not perfect, since it involves shadowing the original GetEnumerator, but it'll do for now, I guess.
  • Anonymous
    February 20, 2004
    For my own reference, I thought I'd compile a quick list of design guidelines added by Brad Abrams, et al.
  • Anonymous
    November 13, 2007
    The comment has been removed
  • Anonymous
    January 20, 2009
    PingBack from http://www.hilpers.com/1041341-framework-1-1-framework-2-a