tags:

views:

78

answers:

4

Why does the following not compile?

interface IFoo
{
void Foo();
}

class FooClass : IFoo
{
void IFoo.Foo() { return; }

void Another() {
   Foo();  // ERROR
 }
}

The compiler complains that "The name 'FooMethod' does not exist in the current context".

However, if the Foo method is changed to:

 public void Foo() { return; }

this compiles just fine.

I don't understand why one works and the other does not.

+2  A: 

Try this:

void Another() {
  ((IFoo)this).Foo();
}

Since you're declaring the Foo method as an explicit interface implementation, you can't reference it on an instance of FooClass. You can only reference it by casting the instance of FooClass to IFoo.

John Bledsoe
+8  A: 

Because when you "explicitly implement" an interface, you can only access the method by casting to the interface type. Implicit casting will not find the method.

void Another()
{
   IFoo f = (IFoo)this:
   f.Foo();
}

Further reading:

http://stackoverflow.com/questions/143405/c-interfaces-implicit-and-explicit-implementation

Adam
A: 

What you have in your code is called explicit interface implementation. If you choose to support an interface like this, these interface methods of your class are not public and can only be called via appropriate interface type references (IFoo in your example).

Alan
+1  A: 

There is actually a really good reason for this behavior. Consider the following code.

public interface IA
{
  IA DoSomething();
}

public interface IB
{
  IB DoSomething();
}

public class Test : IA, IB
{
  public IA DoSomething() { return this; }

  IA IA.DoSomething() { return this; }

  IB IB.DoSomething() { return this; }
}

In this scenario the Test class must implement at least one of the DoSomething methods explicitly because it is not legal to declare two different methods with the same signature. If you were to examine the IL you would see that explicitly implementing an interface decorates the member name automatically so that no two members with the same name exist in the same class. And to be able to call each of the 3 different DoSomething variations above you have to invoke the member from a reference of the correct type. That is how the compiler knows to bind to the correct member.

public static void Main()
{
  var test = new Test();
  test.DoSomething(); // Compiler binds to the implicit implementation.
  var a = (IA)test;
  a.DoSomething(); // Compiler binds to the IA implementation.
  var b = (IB)test;
  b.DoSomething(); // Compiler binds to the IB implementation.
}
Brian Gideon