Ошибка компиляции: "Модификатор" public "недействителен для этого элемента", в то время как явно реализует интерфейс
Я получаю эту ошибку при создании метода public
для класса для явной реализации interface
. У меня есть обходное решение: удалив явную реализацию метода PrintName
. Но я удивлен, почему я получаю эту ошибку.
Может кто-нибудь объяснить ошибку?
Код для библиотеки:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test.Lib1
{
public class Customer : i1
{
public string i1.PrintName() //Error Here...
{
return this.GetType().Name + " called from interface i1";
}
}
public interface i1
{
string PrintName();
}
interface i2
{
string PrintName();
}
}
Код для тестового приложения консоли:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Test.Lib1;
namespace ca1.Test
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
Console.WriteLine(customer.PrintName());
//i1 i1o = new Customer();
//Console.WriteLine(i1o.printname());
//i2 i2o = new Customer();
//Console.WriteLine(i2o.printname());
}
}
}
Ответы
Ответ 1
При использовании явной реализации интерфейса члены в принудительном порядке вынуждены использовать что-то более ограниченное, чем private. И когда модификатор доступа принудительно, вы можете его не добавлять.
Аналогично, в самом интерфейсе все члены public. Если вы попытаетесь добавить модификатор внутри интерфейса, вы получите аналогичную ошибку.
Почему явные члены (очень) частные? Рассмотрим:
interface I1 { void M(); }
interface I2 { void M(); }
class C : I1, I2
{
void I1.M() { ... }
void I2.M() { ... }
}
C c = new C();
c.M(); // Error, otherwise: which one?
(c as I1).M(); // Ok, no ambiguity.
Если эти методы были общедоступными, у вас будет столкновение имен, которое не может быть разрешено нормальными правилами перегрузки.
По той же причине вы даже не можете вызвать M()
изнутри члена class C
. Перед тем, как избежать одной и той же двусмысленности, вам придется отбрасывать this
на определенный интерфейс.
class C : I1, I2
{
...
void X()
{
M(); // error, which one?
((I1)this).M(); // OK
}
}
Ответ 2
http://msdn.microsoft.com/en-us/library/aa288461(VS.71).aspx:
Когда элемент явно реализован, к нему нельзя получить доступ через экземпляр класса, но только через экземпляр интерфейса.
Customer customer = new Customer();
Console.WriteLine(customer.PrintName());
Нарушает это
Ответ 3
Вы не можете использовать модификаторы доступа при явной реализации интерфейса. Член будет привязан к интерфейсу в любом случае, поэтому нет необходимости указывать модификатор доступа, поскольку все члены интерфейса всегда являются общедоступными, и все явно реализованные члены могут быть доступны только через член типа интерфейса (см. например, ответ statichippo).
Ответ 4
Это явная реализация, область по умолчанию для членов интерфейса является общедоступной, тогда как она является частной в случае класса, ergo, нет необходимости использовать модификатор Public, потому что, когда мы вызываем этот метод, он будет вызывается только с ссылкой интерфейса.
В соответствии с "" Явная реализация интерфейса MSDN", функции, реализующие явные интерфейсы, никогда явно не определены публично. Они являются общедоступными по умолчанию. Было бы бессмысленно определять их в противном случае.
Ответ 5
Если мы хотим перейти с неявной реализацией для приведенного выше примера, следующим будет код.
interface I1 { void M(); }
interface I2 { void M(); }
class C : I1, I2
{
public void M() { ... }
}
C c = new C();
c.M(); // Ok, no ambiguity. Because both Interfaces gets implemented with one method definition.