views:

111

answers:

3

Sorry for the vague title, but I'm not sure what this is called.

Say I add IDisposable to my class, Visual Studio can create the method stub for me. But it creates the stub like:

void IDisposable.Dispose()

I don't follow what this syntax is doing. Why do it like this instead of public void Dispose()?

And with the first syntax, I couldn't work out how to call Dispose() from within my class (in my destructor).

A: 

Visual studio gives you two options:

  • Implement
  • Implement explicit

You normally choose the first one (non-explicit): which gives you the behaviour you want.

The "explicit" option is useful if you inherit the same method from two different interfaces, i.e multiple inheritance (which isn't usually).

ChrisW
+1  A: 

When you implement an interface member explicitly, which is what the generated code is doing, you can't access the member through the class instance. Instead you have to call it through an instance of the interface. For example:

class MyClass : IDisposable
{
  void IDisposable.Dispose()
  {
    // Do Stuff
  }

  ~MyClass()
  {
    IDisposable me = (IDisposable)this;
    me.Dispose();
  }
}

This enables you to implement two interfaces with a member of the same name and explicitly call either member independently.

interface IExplict1 
{
  string InterfaceName();
}

interface IExplict2
{
  string InterfaceName();
}

class MyClass : IExplict1, IExplict2 
{
  string IExplict1.InterfaceName() 
  {
    return "IExplicit1";
  }

  string IExplict2.InterfaceName() 
  {
    return "IExplicit2";
  }
}

public static void Main() 
{
  MyClass myInstance = new MyClass();

  Console.WriteLine( ((IExplcit1)myInstance).InstanceName() ); // outputs "IExplicit1"

  IExplicit2 myExplicit2Instance = (IExplicit2)myInstance;

  Console.WriteLine( myExplicit2Instance.InstanceName() ); // outputs "IExplicit2"
}
MaxCarey
+1  A: 

Members of an interface type are always public. Which requires their method implementation to be public as well. This doesn't compile for example:

interface IFoo { void Bar(); }

class Baz : IFoo {
    private void Bar() { }   // CS0737
}

Explicit interface implementation provides a syntax that allows the method to be private:

class Baz : IFoo {
    void IFoo.Bar() { }   // No error
}

A classic use for this is to hide the implementation of a base interface type. IEnumerable<> would be a very good example:

class Baz : IEnumerable<Foo> {
    public IEnumerator<Foo> GetEnumerator() {}
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { }
}

Note how the generic version is accessible, the non-generic version is hidden. That both discourages its use and avoids a compile error because of a duplicate method.


In your case, implementing Dispose() explicitly is wrong. You wrote Dispose() to allow the client code to call it, forcing it to cast to IDisposable to make the call doesn't make sense.

Also, calling Dispose() from a finalizer is a code smell. The standard pattern is to add a protected Dispose(bool disposing) method to your class.

Hans Passant