Какую доступность имеет явно реализованный метод? - PullRequest
2 голосов
/ 03 июля 2019

Итак, мой друг сказал, что явно реализованные методы интерфейса являются частными.

Рассмотрим этот пример для аргумента:

interface ITest
{
    void Test();
}

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

Я не поверил, и приведу аргументы с обеих сторон:

Его:

Я:

  • Вы не можете получить доступ к методу Test изнутри класса, если вы не приведете себя к ITest (именно так работают явно реализованные методы, но вы не должны иметь возможность вызывать метод из класса, если он действительно был приватный метод внутри этого класса?)
  • Когда вы приводите Test -экземпляр к ITest, метод Test становится общедоступным и может вызываться из любого места, поэтому он не может быть закрытым.
  • Я не знаю, насколько это правдоподобно, но в этом ответе указано, что "явно реализованный элемент интерфейса" является открытым.

Я думаю, что мы оба знаем, как работает Явная реализация интерфейса и как ее использовать, но прямо здесь мы не уверены, кто прав.
Вопрос действительно сводится к этому:

Можете ли вы вызвать метод Test в классе Test как "закрытый метод"?

1 Ответ

3 голосов
/ 03 июля 2019

Явные методы интерфейса имеют private уровень доступа.

Давайте посмотрим (с помощью Отражение ):

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

Результат:

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  

Так что мы не можем выполнить их явно:

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(); 

Поскольку мы не можем поставить имя метода таким, какое оно есть, единственный способ прямого вызова ITest.Test - это отражение:

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]);
  } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...