简体   繁体   中英

Why does a method prefixed with the interface name not compile in C#?

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.

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:

C# Interfaces. Implicit implementation versus Explicit implementation

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.

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.
}

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM