Warm tip: This article is reproduced from stackoverflow.com, please click
c# interface

What accessibility does an explicitly implemented method have?

发布于 2020-03-27 10:26:50

So my friend said that explicitly implemented interface methods are private.

Consider this example for the argument:

interface ITest
{
    void Test();
}

class Test : ITest
{
    // IS THIS METHOD PRIVATE?
    void ITest.Test()
    {
        Console.WriteLine("What am I?");
    }
}

I did not believe that and I will list the arguments on both sides:

Him:

Me:

  • You cannot access the Test method from inside the class unless you cast yourself to ITest (which is how explicitly implemented methods work but shouldn't you be able to call the method from inside the class if it really was a private method inside that class?)
  • When you cast a Test-instance to ITest, the Test method becomes publicly available and can be called from anywhere hence it cannot be private.
  • I don't know how credible this is but in this answer it is stated that "explicitly implemented interface member" are public.

I think we both know how Explicit Interface Implementation works and how to use it but right here we aren't sure who's right.
The question really boils down to this:

Can you call the Test method in the Test class a "private method"?

Questioner
Joelius
Viewed
40
Dmitry Bychenko 2019-07-03 23:32

Explicit interface methods have private access level.

Let's have a look (with a help of Reflection):

  using System.Reflection;

 ...

  var result = typeof(Test)
    .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
    .Select(info => $"{(info.IsPrivate ? "private" : "not private")} {info.Name}");

  string report = string.Join(Environment.NewLine, result);

  Consolw.Write(report);

Outcome:

private WFA_Junk_4.Form1.ITest.Test // <- Method of interest
not private Equals
not private GetHashCode
not private Finalize
not private GetType
not private MemberwiseClone
not private ToString  

So we can't execute them explictly:

Test test = new Test();

// ITest.Test() call which is OK
(test as ITest).Test();

// Doesn't compile: 
//   1. Private method
//   2. Wrong name; should be typeof(ITest).FullName.Test() which is not allowed 
test.Test(); 

Since we can't put methods name as it is, the only way, as I can see to call ITest.Test directly is reflection:

class Test : ITest {
  ...
  public void SomeMethod() 
  {
     // we can't put method's name as it is `SomeNamespace.ITest.Test`
     // Let's find it and execute
     var method = this
       .GetType()
       .GetMethod($"{(typeof(ITest)).FullName}.Test", 
                    BindingFlags.Instance | BindingFlags.NonPublic);

     method.Invoke(this, new object[0]);
  }